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