Является ли typedef для себя разрешенным по параметрам шаблона

Я читал чужой код, когда наткнулся на этот фрагмент (урезанный до MWE):

template<typename R> class Test {
    public:
        typedef R R;
};

Здесь есть typedef параметра шаблона самому себе, и это заставило GCC и clang (с -std=c++2a или без него) жаловаться:

test.cc:3:19: ошибка: объявление параметра шаблона тени 'typedef R Test::R'

Однако ICC и MSVC в Compiler Explorer принимают эту часть.

Я прочитал этот вопрос, и предполагается, что typedef себе обычно не подходит. Однако здесь, похоже, это не так. Я также обнаружил, что этот вопрос связан но я думаю, что они должны быть разными, так как здесь мы используем typedef.

Итак, вот вопрос:
Разрешено ли такое переопределение стандартом? Есть ли побочные эффекты этого утверждения? Почему можно так написать?


person M. Zhang    schedule 13.07.2021    source источник
comment
Вы можете написать его, чтобы предоставить R чему-то еще, кто знает, что ему передается экземпляр Test, но не обязательно знает, что такое R. Это похоже на то, как std::vector<T> имеет std::vector<T>::value_type.   -  person Nathan Pierson    schedule 13.07.2021
comment
@LanguageLawyer К сожалению, я думал, что был осторожен. Но все равно спасибо всем.   -  person M. Zhang    schedule 14.07.2021


Ответы (1)


Нет. Имя параметра шаблона не может быть переобъявлено .

Имя параметра шаблона не может быть повторно объявлено в пределах его области (включая вложенные области). Параметр шаблона не может иметь то же имя, что и имя шаблона.

template<class T, int N>
class Y {
    int T;                 // error: template parameter redeclared
    void f()
    {
        char T;            // error: template parameter redeclared
    }
};
 
template<class X> class X; // error: template parameter redeclared

Из стандартного [temp.local]/6:

Имя параметра-шаблона не должно быть привязано ни к какому последующему объявлению, содержащемуся в области, к которой принадлежит параметр-шаблона. [Пример 5:

template<class T, int i> class Y {
  int T;                                // error: template-parameter hidden
  void f() {
    char T;                             // error: template-parameter hidden
  }
  friend void T();                      // OK: no name bound
};

template<class X> class X;              // error: hidden by template-parameter

— конец примера]

person songyuanyao    schedule 13.07.2021