I never saw a nested-name-specifier in an elaborated-type-specifier before this question, and at first glance I thought it wasn't even covered by the grammar. Now I see that since C++98 up to the present, it's translated as a special case without the typename-specifier construct. C++11 7.1.6.3/2 (7.1.5.3/2 in C++98):
3.4.4 describes how name lookup proceeds for the identifier in an elaborated-type-specifier. If the identifier resolves to a class-name or enum-name, the elaborated-type-specifier introduces it into the declaration the same way a simple-type-specifier introduces its type-name.
Therefore it would seem that although you can form a qualified elaborated-type-specifier, you need to take care that it's never type-dependent. Name resolution per 3.4.4 at template definition time will never find a class-name because dependent names are presumed to be objects unless prefixed with the typename
keyword, which isn't grammatically allowed in this context.
Is this an accurate assessment of the meaning of the standard, and the design intent of the language?
Expanding from the comments:
Take this program as an example:
template <typename T>
struct S1 { struct I { }; };
template <typename T>
struct S2 { typedef struct S1<T>::I I; }; // okay
template <typename T>
struct S3 { typedef struct S2<T>::I I; }; // okay at definition time
// usually error at instantiation time
template <>
struct S2<short> : S1<short> { };
int main() {
S1<int>::I a;
S2<int>::I &b = a; // okay
S3<int>::I &c = b; // error
S1<short>::I d;
S2<short>::I &e = d; // okay
S3<short>::I &f = e; // okay
}
At template definition time, both S2
and S3
are okay: 14.6p5 lists the exceptions where typename
is not required. Essentially: where the use is unambiguous because the name can never be anything other than a type, typename
is not required. This includes several cases where typename
is not syntactically allowed, so where requiring typename
would mean there is no way to write the program. Both typename struct S<T>::I
and struct typename S<T>::I
are hard errors, and struct S<T>::I
is unambiguous.
At template instantiation time, the rules of 3.4.4 are clearer: both struct S1<int>::I
and struct S2<int>::I
can then be found, where it becomes apparent that S2<int>::I
is a typedef, so struct S2<int>::I
is an error. At the same time, at that point, S2<short>::I
is seen not to be a typedef, but a struct, so struct S2<short>::I
is allowed.