Draft N3337 of the C++11 standard states in [namespace.udecl]
A using-declaration introduces a name into the declarative region in which the using-declaration appears.
Every using-declaration is a declaration and a member-declaration and so can be used in a class definition.
In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined.
This is generally used to make a protected typedef within a base-class public in the derived class, as in the following example, which compiles successfully in the latest version of Clang:
struct A
{
protected:
typedef int Type;
};
struct B : A
{
using A::Type;
};
B::Type x;
The using-declaration can refer to a template class. This compiles:
struct A
{
protected:
template<typename T>
struct Type
{
};
};
struct B : A
{
using A::Type;
};
B::Type<int> x;
It's also possible to refer to a template in a dependent base-class. The following compiles successfully (with the typedef commented.)
template<typename T>
struct A
{
protected:
template<typename U>
struct Type
{
};
};
template<typename T>
struct B : A<T>
{
using /* typename */ A<T>::Type; // A<T> is dependent, typename required?
// typedef Type<int> IntType; // error: unknown type name 'Type'
};
B<int>::Type<int> x;
Uncommenting the typename
causes an error when instantiating B<int>
: "error: 'typename' keyword used on a non-type".
Uncommenting the typedef causes an error when parsing B
before its first instantiation. I'm guessing this is because the compiler does not treat Type
as a dependent type-name.
The last paragraph of [namespace.udecl]
suggests that using-declarations may specify dependent names, and that the typename
keyword must be used in order to disambiguate further usage of the name introduced:
If a using-declaration uses the keyword typename and specifies a dependent name (14.6.2), the name introduced by the using-declaration is treated as a typedef-name
My reading of [temp.dep]
suggests that A<T>::Type
is a dependent name. It follows logically that the name introduced by the using-declaration should also be dependent, but [temp.dep]
does not explicitly mention the case of a dependent using-declaration. Am I missing something?
The problem is that Type
is not a class, but a class template. You can do the following (this way you tell the compiler that Type
is a class template in scope of B
):
template<typename T>
struct B : A<T>
{
using A<T>::Type;
typedef typename B::template Type<int> IntType;
};
Actually, in your second example in order to write typedef
for IntType
you'd have to do the same.
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