Should a declaration member with a dependent identifier be a dependent name?

Draft N3337 Standard State C ++ 11 in [namespace.udecl]

Use-declarations introduces the name into the declarative region in which the declaration of use appears.

Each declaration of use is a declaration and declaration of a member and therefore can be used in the definition of a class.

In the declaration of use used as a member declaration, the naming specifier must name the base class the class is defined.

This is usually used to create a protected typedef in a public base class class in a derived class, as in the following example, which successfully compiles in the latest version of Clang:

 struct A { protected: typedef int Type; }; struct B : A { using A::Type; }; B::Type x; 

A using declaration may 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; 

You can also refer to a template in a dependent base class. The following compilation is successful (with typedef comments.)

 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 typename causes an error when instantiating B<int> : "error: keyword 'typename' used for non-type.

Uncommenting typedef causes an error while parsing B before its first instance. I assume this is because the compiler does not treat Type as a dependent type name.

The last paragraph [namespace.udecl] indicates that use-declarations may indicate dependent names and that the typename keyword should be used in order to eliminate further use of the entered name:

If use-declaration uses the typename keyword and specifies the dependent name (14.6.2), the name entered using the declaration-declaration is treated as typedef-name

My reading of [temp.dep] suggests that A<T>::Type is a dependent name. It follows logically that the name entered using the declaration-declaration must also be dependent, but [temp.dep] does not explicitly mention the case of dependent use-declaration. Did I miss something?

+7
c ++ language-lawyer templates dependent-name using-declaration
source share
2 answers

The problem is that Type 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 B ):

 template<typename T> struct B : A<T> { using A<T>::Type; typedef typename B::template Type<int> IntType; }; 

Actually, in your second example, to write a typedef for IntType , you will need to do the same.

+2
source share

Yes, using a class member declaration with a dependent identifier identifier introduces a dependent name.

[namespace.udecl]

Use-declarations introduces the name into the declarative region in which the declaration of use appears.

If the name entered is dependent, it remains dependent - I cannot find anything to suggest otherwise.

However, using-declaration syntax does not provide a way to indicate that the dependent name is a template. Subsequent references to the Type dependent name inside B may or may not refer to the template, so Type<int> cannot be parsed.

The following example demonstrates the correct use of a dependent use-declaration.

 template<typename T> struct A { protected: struct Type { typedef int M; }; }; template<typename T> struct B : A<T> { using typename A<T>::Type; typedef typename Type::M Type2; }; B<int>::Type2 x; 
0
source share

All Articles