字符串字面量模板参数
非类型模板参数只能是常量整数值(包括枚举)、对象/函数/成员的指针、对象或函数的左值引用、
std::nullptr_t
(
nullptr
的类型)。对于指针,在
C++17
之前需要外部或者内部链接。然而,自从
C++17
起,
可以使用无链接的指针。然而,
你仍然不能直接使用字符串字面量。
例如:
template<const char* str>
class Message {
...
};
extern const char hello[] = "Hello World!"; // 外部链接
const char hello11[] = "Hello World!"; // 内部链接
void foo()
{
Message<hello> msg; // OK(所有C++标准)
Message<hello11> msg11; // 自从C++11起OK
static const char hello17[] = "Hello World!"; // 无链接
Message<hello17> msg17; // 自从C++17起OK
Message<"hi"> msgError; // ERROR
}
Message<hello17> msg17;
在c++11
会有如下报错
source>:17:20: error: '& hello17' is not a valid template argument of type 'const char*' because 'hello17' has no linkage
17 | Message<hello17> msg17; // 自从C++17起OK
| ^
也就是说自从C++17
起你仍然需要至少两行才能把字符串字面量传给一个模板参数。
例如 Message<"hi"> msgError;
会报如下错误:
<source>:19:17: error: '"hi"' is not a valid template argument for type 'const char*' because string literals can never be used in this context
19 | Message<"hi"> msgError; // ERROR
| ^
然而,你现在可以把第一行写在和实例化代码相同的作用域内。
这个特性还解决了一个不幸的约束:自从C++11
起可以把一个指针作为模板实参:
template<int* p> struct A {
};
int num;
A<&num> a; // 自从C++11起OK
但不能用一个返回指针的编译期函数作为模板实参,然而现在可以了:
int num;
...
constexpr int* pNum() {
return #
}
A<pNum()> b; // C++17之前ERROR,现在OK