Вложенные классы являются зависимыми типами в шаблонах классов?

Учтите следующее:

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?

1 ответ

Решение

Да вы правы.

В вашем случае это не имеет значения, потому что вы не можете специализироваться T1 без создания экземпляров m (поскольку это член класса). Но вы могли бы сделать это, положить m в функции:

template<class> struct T
{
    struct T1
    {
        struct T2
        {

        };
    };

    void foo() {
        typename T1::T2 m;
    }
};

template<>
struct T<void>::T1 {
    int T2;
};

Если T1 не зависят, ваш код может изменить смысл, потому что T2 будет ссылаться на значение, а не тип.

Другие вопросы по тегам