一些我不理解的代码:
template<const char *T>
class A
{
};
const char *arr="hello world";
int main()
{
A<arr> obj;
}
此代码段无法编译。
visual studio编译器的错误消息为:
Invalid template argument for 'A', expected compile-time constant expression
g++的错误消息为:
'arr' is not a valid template argument because 'arr' is a variable , not the address of a variable
对于visualstudio编译器,即使在我将const
更改为constexpr
之后,该代码仍然无法编译。
为什么?这与内部链接和外部链接++模板这本书,但不明白为什么以及如何)
此外,将const char *arr = "Hello world";
更改为
const char arr[] = "Hello world";
或
external const char *arr="Hello world";
不会起作用。
但这会起作用:external const char arr[]="Hello world";
这个问题比您所做的要简单。Visual Studio编译器的错误消息实际上非常清楚。arr
不是有效的模板参数,因为它不是编译时常数。
为了使用字符串作为模板非类型参数,它必须是一个具有外部链接的变量(尽管我相信C++11确实删除了这一要求——请参阅Columbo的回答)。因此,您可以将代码更改为以下内容,这样就可以工作了:
template <const char* T>
class A
{
// ...
};
extern const char arr[] = "hello world";
int main()
{
A<arr> obj;
}
请注意arr
的声明是如何更改的。该变量现在是一个具有外部链接的命名对象,因此可以用作模板非类型参数。
基本上,它的地址被传递到模板。这意味着决定其唯一性的不是字符串的内容,而是对象本身。换句话说,如果有两个不同的变量持有完全相同的字符串,那么它们将具有不同的类型,并创建模板类的两个不同实例。
指针类型的模板参数不允许引用字符串文字([temp.arg.notype]/(1.3))。相反,请声明一个全局数组:
constexpr char arr[] = "hello world"; // Or use const only, but won't be able to
// use it inside the template
这可以用作模板参数,因为它可以出现在常量表达式中,并且具有静态存储持续时间,使其成为常量表达式([expr.const]/5)的允许结果。