Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can C++ struct static member variables shadow non type template parameters?

msvc compiles the following code(with /permissive- compiler switch), clang and gcc do not:

template<auto val>
struct S{
    static constexpr auto val = val;
};
int main() {
    return S<4>::val;
}

I presume that this is just a msvc bug, but I am curious if maybe standard is ambiguous here.

like image 368
NoSenseEtAl Avatar asked Aug 09 '21 13:08

NoSenseEtAl


People also ask

What are the rules for class templates and static variables?

Class templates and static variables: The rule for class templates is same as function templates Each instantiation of class template has its own copy of member static variables. For example, in the following program there are two instances Test and Test.

What are non-type parameters in C++?

Non-type parameters. A template non-type parameter is a special type of parameter that does not substitute for a type, but is instead replaced by a value. A non-type parameter can be any of the following: A value that has an integral type or enumeration; A pointer or reference to a class object;

When is a non-type template parameter unmodifiable?

When the name of a non-type template parameter is used in an expression within the body of the class template, it is an unmodifiable prvalue unless its type was an lvalue reference type, or unless its type is a class type (since C++20) .

What is a template parameter in C++?

A template type parameter is a placeholder type that is substituted for a type passed in as an argument. However, template type parameters are not the only type of template parameters available. Template classes and functions can make use of another kind of template parameter known as a non-type parameter.


2 Answers

The standard is unambiguous on this, a template parameter can't be redeclared for any reason, see [temp.local]/6:

A template-parameter shall not be redeclared within its scope (including nested scopes). A template-parameter shall not have the same name as the template name.

[ Example:

template<class T, int i> 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

— end example ]

So MSVC behavior (given the /permissive- flag) looks like a bug.

like image 123
rustyx Avatar answered Dec 10 '22 00:12

rustyx


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

A declaration of a static data member plainly binds a name, so it is just as ill-formed.

like image 23
T.C. Avatar answered Dec 10 '22 01:12

T.C.