4

I was reading someone else's code when I came across this piece (stripped to MWE):

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

Here there is a typedef of the template parameter to itself, and it made GCC and clang (with or without -std=c++2a) complain:

test.cc:3:19: error: declaration of 'typedef R Test::R' shadows template parameter

However, ICC and MSVC on Compiler Explorer both accept that piece.

I've read this question, and it is suggested that a typedef to self is usually a no-op. However, here it does not seem to be the case. I've also found this question to be related but I think they should be different since here we are using a typedef.

So here is the question:
Is this kind of redefinition allowed by the standard? Are there any side effects of that statement? Why might one write that?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
M. Zhang
  • 750
  • 8
  • 18
  • You might write it to expose `R` to something else that knows is handed an instantiation of `Test` but doesn't necessarily know what `R` was. It's like how `std::vector` has `std::vector::value_type`. – Nathan Pierson Jul 13 '21 at 01:55
  • Dup of [In a C++ template class, can I typedef the template parameter using the same name?](https://stackoverflow.com/questions/16613773/in-a-c-template-class-can-i-typedef-the-template-parameter-using-the-same-nam) or [Is it allowed to typedef a class template type argument into the same name?](https://stackoverflow.com/questions/38063271/is-it-allowed-to-typedef-a-class-template-type-argument-into-the-same-name) – Language Lawyer Jul 14 '21 at 14:07
  • @LanguageLawyer Oops, I thought I was careful. But still thanks to everyone. – M. Zhang Jul 14 '21 at 17:02

1 Answers1

4

No. The name of a template parameter is not allowed to be redeclared.

The name of a template parameter is not allowed to be redeclared within its scope (including nested scopes). A template parameter is not allowed to have the same name as the template name.

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

From the standard, [temp.local]/6:

The name of a template-parameter shall not be bound to any following declaration contained by the scope to which the template-parameter belongs. [Example 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

— end example]

songyuanyao
  • 169,198
  • 16
  • 310
  • 405