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.
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.
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 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) .
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.
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.
[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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With