Scope of Using Declaration Within a Namespace

scope of using declaration within a namespace

No, it is not safe - it won't pollute another namespace, but it is dangerous for other reasons:

A using directive will import anything that is currently visible by the name you specify into the namespace where you use it. While your using will only be visible to users of MyNamespace, other things from "outside" will be visible to your using declaration.

So how is this dangerous when used in a header? Because it will import things that are visible at the point of the declaration, the exact behavior will depend on the order of headers you include before the declaration (There might be different things visible from boost::numeric::ublas::vector). Since you cannot really control which headers are included before your header (nor should you be! headers should be self-sufficient!), this can lead to very strange problems where your function will find one thing in one compilation unit, and another in the next.

As a rule of thumb, using declarations should only be used after all includes in a .cpp file. There's also an item on this exact issue in the book "C++ Coding Standards" by Sutter and Alexandrescu (Item 59). Here's a quote:

But here's the common trap: Many people think that using declarations issued at namespace level (...) are safe. They are not. They are at least as dangerous, and in a subtler and more insidious way.

Even when it's unlikely that the name you are using doesn't exist anywhere else (as is probably the case here), things can get ugly: In a header, all declarations should be fully qualified. This is pain, but otherwise, strange things can happen.

Also see Migrating to Namespaces, Using-declarations and namespace aliases and Namespace Naming for examples and the problem described in-depth.

Scope of `using namespace` within another namespace

The standard says that (7.3.4/2)

A
using-directive
specifies that the names in the nominated namespace can be used in the scope in which the
using-directive
appears after the
using-directive
.

namespace A {  \
int i = 9; | <-- namespace A scope.
} /

namespace B { \
using namespace A; | <-- namespace B scope. "i" is visible after
void bar() | the "using namespace" line.
{ |
i += 1; /*Ok*/ |
} |
} /

namespace B { \
void foo() |
{ | <-- still namespace B scope. "i" is still visible
i += 1; /*Ok*/ |
} |
} /

So stuff made visible with this using directive will be visible everywhere in A scope after the using namespace B line. Of course, if you do this in a header file, all the stuff will be visible everywhere where you include that header file, so you should not really use "using namespace..." anywhere in the headers.

What's the scope of the using declaration in C++?

When you #include a header file in C++, it places the whole contents of the header file into the spot that you included it in the source file. So including a file that has a using declaration has the exact same effect of placing the using declaration at the top of each file that includes that header file.

Scope a using declaration, inside a header

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);
}
}

Trying to define namespace member via using-declaration

Current working draft N4527, [8.3p1]:

[...] When the declarator-id is qualified, the declaration shall refer to a
previously declared member of the class or namespace to which the
qualifier refers (or, in the case of a namespace, of an element of the
inline namespace set of that namespace (7.3.1)) or to a specialization
thereof; the member shall not merely have been introduced by a
using-declaration in the scope of the class or namespace nominated by
the nested-name-specifier of the declarator-id. [...]

So, definitely ill-formed; GCC and MSVC are wrong.



Related Topics



Leave a reply



Submit