template<typename T, T nontype_param>
class C {};
int a[10];
C<int *, &a[0]> err3;
The code above will throw an error when the standard of c++ is lower than 17, while it will be ok when the standard is 17. Could someone explain the reasons to me?
According the information on the cppreference:
The only exceptions are that non-type template parameters of reference or pointer type and non-static data members of reference or pointer type in a non-type template parameter of class type and its subobjects(since C++20) cannot refer to/be the address of
or a subobject (including non-static class member, base subobject, or array element) of one of the above(since C++20).
(The words in cppreference are formatted, and I am unsure how to correctly paste it here in markdown. If you are confused by my reference, please click the link and find the section to read. )
I think using the address of the first element of the array as template non-type argument should not pass even in c++ 17.
tldr;
The answer depends on which standard c++ version you're using as explained below. In C++20 the program is well-formed while in C++17 it is ill-formed. The important thing to note is that
ahas static storage duration and that c++20 allows the address of certain subobjects(as opposed to C++17 which didn't allow "any" subobject address) to be template arguments.C++20
The program is well-formed in c++20 as per temp.arg.nontype:
(emphasis mine)
Since
&a[0]is neither of the above things mentioned in the list, the program is well-formed.Also note that the template argument must be a converted constant expression which is true here. From temp.arg:
Note a converted constant expression should also be a constant expression as per expr.const:
Now we move onto constant expression
C++17
In C++17, the program is ill-formed as per temp.arg:
(emphasis mine)