Вложенные классы являются зависимыми типами в шаблонах классов? - PullRequest
0 голосов
/ 29 июня 2018

Рассмотрим следующее:

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 Ответ

0 голосов
/ 29 июня 2018

Да, вы правы.

В вашем случае это не имеет значения, потому что вы не можете специализировать 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 будет ссылаться на значение, а не на тип.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...