Scope a using declaration, inside a header - c++

Unfortunately I'm bound to using a thirdparty macro which assumes that I am within the namespace thirdparty. However this macro declares some types which I need to be outside of the thirdparty namespace, so I can't use this snippet:
namespace thirdparty
{
TP_MACRO(my_type_name, inner);
}
If I did, all of my declared types would be in the thirdparty:: namespace which won't work.
The issue is that the TP_MACRO is using types from inside of the thirdparty namespace without qualifying them. To get arround the this I am currently bringing these types into the current scope with using declarations:
using thirdparty::type1;
using thirdparty::type2;
TP_MACRO(my_type_name, inner);
The downside of this approach is that I'm polluting the global namespace with these types, which is generally bad practice (this code is in a header file).
I can wrap the above snippet in a new namespace (which I am doing), but I would like to know if there is a way to scope these using declarations so that after the macro has declared my types, I can remove them from the surrounding namespace?
The TP_MACRO is similar to (but is more complex in reality):
#define TP_MACRO (name, inner) \
typedef type1<inner> type1_##name; \
typedef type2<inner> type2_##name;
It is also subject to change, hence why I would avoid copying it's contents.

Try declaring the types in an embedded namespace inside thirdparty so that the macro is happy, then alias that namespace so that it's accessible globally:
namespace thirdparty::myns {
TP_MACRO(my_type_name, inner);
}
namespace myns = thirdparty::myns;
If you are not using C++17, then use:
namespace thirdparty {
namespace myns {
TP_MACRO(my_type_name, inner);
}
}

I can wrap the above snippet in a new namespace (which I am doing)
That's what you should be doing.
I would like to know if there is a way to scope these using declarations so that after the macro has declared my types, I can remove them from the surrounding namespace?
No.
Also I suggest making a recommendation upstream that they improve these macros.

Related

using standard namespace in C plus plus

Consider this
#include<headerfile1>
#include<headerfile2>
.
.
#include<headerfilen>
using namespace std;
when I write this(header files are all in standard library of C++),does std namespace of all header files come into picture?
Also, if there are two libraries h1 and h2 and both have same namespace x and in those namespaces have same function func(). How do I resolve this?
From cppreference:
A using-directive that names the inline namespace is implicitly
inserted in the enclosing namespace (similar to the implicit
using-directive for the unnamed namespace).
For instance, in the following example, using namespace std::string_literals makes the operator visible inside the scope:
{ // in C++14, std::literals and its member namespaces are inline
using namespace std::string_literals; // makes visible operator""s
// from std::literals::string_literals
auto str = "abc"s;
}
If you use the using directive outside a scope (for instance as in your example), pain will follow, as the commenters stated, especially if this file is a header file: this namespace will be implicitly imported to any file that includes this one. This is why the proper way of managing a big project is to create your own namespace and put all your custom objects in that new namespace. If you really must use a using directive, do so in the implementation file, never in the header, and ideally within scopes.
This will help you avoid most conflicts, unless your namespace uses a common name:
namespace Matrix{ <--- Bad practice, Matrix will probably conflict with something
myStuff ...
}
namespace JohnsAwesomeMatrix236790{ <--- Namespace name is unique,unlikely to get conflicts.
myStuff ...
}
Also, it is much safer to import the few functions that you use instead of the entire namespace:
using namespace std; // Imports the entire namespace!
using std::cout; // Much better, we only import
using std::endl; // the names of the two functions we use a lot
Any decently written library you include will make very careful use of the using directive (if at all), so you normally don't have to worry about this. However, if you use code written with less stringent standards (e.g., scientific code) this is something to look out for.

What's the purpose of declaring "namespace std {}"?

In some piece of code, I saw this declaration without understanding the exact meaning...
namespace std {}; // why?
using namespace std;
int main(){
...
}
That's a forward declaration of a namespace. You are not allowed to 'use' a namespace before it has been declared, so the declaration is necessary if you don't have any includes that bring in any part of 'std' beforehand.
Is it actually useful or necessary... That's doubtful. If you are including anything that brings in any part of std, you don't need the forward declaration. And if you are not, you don't need that using namespace std. So it might be a bit of boilerplate code - someone who was taught to 'always write using namespace std', and writes it even if it doesn't make any sense.
There is no point. I guess that code was written by someone who didn't really know what they were doing.
You'll get access to the namespace as soon as you include something anyway, so forward declaring it here doesn't really serve any purpose.
Contrary to the answers given above, I want to demonstrate a particular case where forward-declaring a namespace can be useful.
I make heavy use of Boost.Log in my application, where I use namespace lg = boost::log; for abbreviating long statements like boost::log::core::get()->.... The alias is declared in a general header file included by all components of my software, but I don't want to have all Boost.Log includes in this file, since not all components use logging. But in order to define the alias, I need to forward-declare boost::log. So my header file contains the following lines:
// boost::log namespace "forward" declaration
namespace boost { namespace log {}}
// Alternatively (from C++17 onwards):
namespace boost::log {}
// Namespace alias for boost::log.
namespace lg = boost::log;
That way, I don't need to define the lg alias in every file, which would be error-prone and tedious (and also I don't need to include the Boost.Log in the global header, which would possibly increase build times a lot).
If boost::log doesn't tell you much, think of other nested namespaces like std::chrono that one might want to alias.

How can I avoiding typing namespace:: overly often in my code?

I use cocos2dx. When I use classes from it I need to type cocos2d:: very often unless I type using namespace cocos2d;.
How can I avoid having to repeat the namespace all the time?
There are several ways to use stuff from other namespaces without having to repeat the namespace on every instance.
Import the entire namespace: using namespace cocos2d; You can now use all members of that namespace by only their name without the namespace prefix. This pollutes your own namespace with possibly quite a few names (depending on the contents of the imported namespace) which might not be desirable.
Import single names from that namespace: using cocos2d::MyClassName; This only imports the given name. The upside is that your namespace is not polluted. The downside is that you will have to do it for every namespace member you want to import. If you only need a few then this approach is fine.
Create a namespace alias: namespace co = cocos2d; Now you can refer to members of the cocos2d namespace as if they were members of the co namespace.
Create a type alias (since C++11): using CoClass = cocos2d::MyClassName; You can then refer to the aliased member with the identifier you chose. This can be especially helpful when an imported type shadows a type in your own namespace.
Chris's answer is correct and complete, but I would add that it's a better idea to explicitly specify every member's namespace to avoid ambiguity in other files that included your header file.
using namespace cocos2d; will implicitly use that namespace in every file that includes your header. You may put it inside the .cpp file. Same thing goes for using cocos2d::MyClassName; and namespace aliases.
Those will all work, but you shouldn't use them.
See that answer to the question: “using namespace” in c++ headers

Should C++ namespace aliasing be used in header files?

It's considered bad practice to employ using namespace in C++ headers. Is it similarly a bad idea to use namespace aliasing in a header, and each implementation file should declare the aliases it wishes to use?
Since headers are the places you tend to use fully specified names (since we don't use namespaces in headers), aliases would be useful but they would still propagate though your source when #included.
What is the best practice here? And what is the scope of a namespace alias?
If you put a namespace alias into your header this alias will become part of your (public) API.
Sometimes this technique is used to do ABI compatible versioning (or at least to make breakage visible) like this:
namespace lib_v1 { ... }
namespace lib_v2 { ... }
namespace lib = lib_v2;
or more commonly:
namespace lib {
namespace v1 {}
namespace v2 {}
using namespace v2;
}
On the other hand if you do it just to save some typing it is probably not such a good idea.
(Still much better than using a using directive)
I do it with unnamed namespaces this way:
#include <whatyouneed>
...
namespace {
typedef ...
using ..
namespace x = ...
// anything you need in header but shouldn't be linked with original name
}
// normal interface
class a: public x::...

How do nested namespaces work?

The Arguments class is defined in the v8::internal namespace
https://github.com/joyent/node/blob/master/deps/v8/include/v8.h#L113
namespace v8 {
// ...
namespace internal {
class Arguments;
}
// ...
}
However, it is later used in the v8 namespace to access it
https://github.com/joyent/node/blob/master/src/handle_wrap.h#L38
using v8::Arguments;
Which leads me to to the question "How do nested namespaces work?".
They work as you would expect. Consider that a single-level namespace (e.g. std::) is already nested in the global namesapce ::. Unless a using namespace std; directive is applied, only the std name is registered in the global namespace and symbols in std:: are not directly visible to the global namespace.
Add the second layer and apply the same logic. Symbols in v8::internal are not directly accessible in either the global namespace or v8::, but a using namespace v8; directive will pull v8 symbols including internal:: (the namespace name, not its contents) into the global namespace etc.
As you surely know, there are other ways to pull a single name into another namespace: using directives and typedef directives. Unless there is another class named v8::Arguments, there is a typedef or using directive pulling v8::internal::Arguments into v8:: as v8::Arguments.
A quick look at the V8 source code in node.js, there is indeed a class named v8::Arguments defined in namespace v8:: at line 1946 and namespace v8::internal:: is not opened until line 3709.