I am learning C using the books listed here. In particular, I learnt that we cannot use std::string
as a non-type template parameter. Now, to further clear my concept of the subject I tried the following example which compiles in gcc and msvc but not in clang. Demo
std::string nameOk[] = {"name1", "name2"};
template<std::string &name>
void foo()
{
}
int main()
{
foo<nameOk[0]>(); //this compiles in gcc and msvc but not in clang in C 20
}
My question is which compiler is right here(if any). That is, is the program well-formed or IFNDR.
CodePudding user response:
Clang is complaining that your template argument is a subobject. (If you make the argument a complete string object, it works.)
This behavior is based on an earlier restriction in the standard at [temp.arg.nontype], which read
For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
- a subobject (6.7.2 [intro.object]),
This restriction is lifted as of P1907 which is in C 20, but Clang hasn't reflected that yet. GCC also fails when you use e.g. version 10 with C 17:
error: '& nameOk[0]' is not a valid template argument of type 'std::string&' {aka 'std::__cxx11::basic_string<char>&'} because 'nameOk[0]' is not a variable
CodePudding user response:
Clang is wrong in rejecting the code as this is allowed by the standard. From temp.param#6:
6) A non-type template-parameter shall have one of the following (possibly cv-qualified) types:
6.1) a structural type (see below),
7) A structural type is one of the following:
7.2) an lvalue reference type, or
(emphasis mine)
This means that std::string&
can be used as a nontype template parameter for which nameOk[0]
is a valid nontype template argument and the program is well-formed.