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?
There is no "using typename directive". There are using-directives and using-declarations.
You're not using any using-directives, and they aren't relevant to the question in any case (they name namespaces, and can't use the typename keyword).
When using-declarations happen to appear within class templates, and happen to name dependent types, they have to use the typename
keyword just like anything else that happens to be in a template and happens to name a dependent type.
For example:
template <typename A, typename R>
class Functor : public std::unary_function<A, R>
{
using typename std::unary_function<A, R>::result_type;
using typename std::unary_function<A, R>::argument_type;
public:
result_type operator() (argument_type) {}
};
In your situations, the namespace-declaration does not appear to be a part of the body of a class template, in fact it appears to be at namespace scope, in which case attempting to name a class member (doesn't matter if it's a type or a function or whatever) violates 7.3.3[namespace.udecl]/8
A using-declaration for a class member shall be a member-declaration
as the compiler correctly diagnosed with "error : using declaration can not refer to class member"
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With