Search code examples
c++templateslanguage-lawyertypedefno-op

Is a typedef to self allowed over template parameters


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?


Solution

  • 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]