Consider the following:
template<class> struct T
{
struct T1
{
struct T2
{
};
};
/*typename*/ T1::T2 m;
};
Without typename
, compilation fails as T2 is considered a dependent name, and thus not a type. After looking to a C++17 draft standard (N4659), I believe I've determined why:
§ 17.6.2.1 ¶ 5
A name is a member of the current instantiation if it is
— An unqualified name that, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
...
A name is a dependent member of the current instantiation if it is a member of the current instantiation that, when looked up, refers to at least one member of a class that is the current instantiation.
T1 is a dependent member of the current instantiation. T2 is not a member of the current instantiation (it is a member of T1),
§ 17.6.2.1 ¶ 9.3
A type is dependent if it is
...
— a nested class or enumeration that is a dependent member of the current instantiation,
...
T1 is a nested class and thus a dependent type.
§ 17.6 ¶ 3
When a qualified-id is intended to refer to a type that is not a member of the current instantiation (17.6.2.1) and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forming a typename-specifier. ...
Thus, typename
is needed.
Is my understanding correct? If so, what's the rationale behind this? How could the lookup of T1::T2
ever find anything other than the T2 nested within T1?