I have some code which looks like this:
namespace myLibrary
{
class A
{
public:
struct Nested
{
...
};
...
};
}
In some other parts of the code, I need to access A. Since I like readable code, I also like the using directive:
using myLibrary::A;
...
A a;
Now, at some point I also need to access my nested class, so I want to write something like this:
using myLibrary::A::Nested;
Obviously, the compiler can't know that this is a nested class and not a class member, and gives me an error:
error : using declaration can not refer to class member
What I can't understand is why this does not solve the problem:
using typename myLibrary::A::Nested;
The compiler still gives me the exact same error!
Luckily, I have alternatives:
// Using a typedef
typedef myLibrary::A::Nested Nested;
// Using the new C++11 syntax for type aliasing
using Nested = myLibrary::A::Nested;
but I'd like to understand why the using typename directive did not work. Does it not do what I think it does? Or is it not implemented by compilers? If it is the latter, is there a reason for it?
A using
declaration referring to a namespace member A
may only appear at namespace or local scope.
A using
declaration referring to a class member Nested
may only appear at class scope (along with member declarations), in a class derived from Nested
. In fact, such using
declarations are grammatically considered to be member declarations. They are used to adjust access qualification, and (with typename
) to allow members of type-dependent bases to be used without qualification. These are specific use cases, so member using
declarations are a bit specialized.
A nested class is a member of its enclosing class. You should generally avoid using class enclosures as a substitute for namespaces. Metaprogramming provides some exceptions to the rule, but in those cases you still wouldn't use using
declarations, at least at namespace scope, because namespaces cannot be templated. Inheriting from an empty metaprogramming class is viable, but do mind the spaghetti.
The using
directive is a different beast. It looks like using namespace
and it links one namespace to another as a fallback path in name lookup.