Рассмотрим следующее:
template<class> struct T
{
struct T1
{
struct T2
{
};
};
/*typename*/ T1::T2 m;
};
Без typename
компиляция завершится неудачно, поскольку T2 считается зависимым именем и, следовательно, не типом. После рассмотрения проекта стандарта C ++ 17 (N4659), я считаю, что я определил, почему:
§ 17.6.2.1 ¶ 5
Имя является членом текущего экземпляра , если оно
- Неквалифицированное имя, которое при поиске относится как минимум к одному члену класса, являющегося текущим экземпляром, или его независимому базовому классу.
...
Имя является зависимым членом текущего экземпляра , если оно является членом текущего экземпляра, который при поиске ссылается по крайней мере на один член класса, являющегося текущим экземпляром.
T1 является зависимым членом текущего экземпляра. T2 не является членом текущего экземпляра (он является членом T1),
§ 17.6.2.1 ¶ 9,3
Тип зависит, если он
...
- вложенный класс или перечисление, являющееся зависимым членом текущего экземпляра,
...
T1 является вложенным классом и, следовательно, зависимым типом.
§ 17,6 ¶ 3
Когда квалифицированный идентификатор предназначен для ссылки на тип, который не является членом текущего экземпляра (17.6.2.1), а его спецификатор вложенного имени относится к зависимый тип, он должен начинаться с ключевого слова typename , образуя typename-спецификатор . ...
Таким образом, typename
необходимо.
Правильно ли мое понимание? Если да, то в чем причина этого? Как поиск T1::T2
может найти что-либо кроме T2, вложенного в T1?