我知道非类型模板参数应该是一个常数整数表达式。有人可以阐明为什么吗?
template <std::string temp>
void foo()
{
// ...
}
error C2993: 'std::string' : illegal type for non-type template parameter 'temp'.
我知道什么是常数积分表达式。不允许std::string
使用上述片段中的非常量类型的原因是什么?
Answers:
之所以不能这样做,是因为在编译期间无法解析和替换非常量表达式。它们可能会在运行时更改,这将需要在运行时生成新模板,这是不可能的,因为模板是编译时的概念。
这是标准允许非类型模板参数(14.1 [temp.param] p4)的内容:
非类型模板参数应具有以下(可选,具有cv限定)类型之一:
- 整数或枚举类型,
- 指向对象或函数的指针,
- 对对象的左值引用或对函数的左值引用,
- 指向成员的指针,
std::nullptr_t
。
那是不允许的。
但是,这是允许的:
template <std::string * temp> //pointer to object
void f();
template <std::string & temp> //reference to object
void g();
参见C ++ Standard(2003)中的§14.1/ 6,7,8。
插图:
template <std::string * temp> //pointer to object
void f()
{
cout << *temp << endl;
}
template <std::string & temp> //reference to object
void g()
{
cout << temp << endl;
temp += "...appended some string";
}
std::string s; //must not be local as it must have external linkage!
int main() {
s = "can assign values locally";
f<&s>();
g<s>();
cout << s << endl;
return 0;
}
输出:
can assign values locally
can assign values locally
can assign values locally...appended some string
std::string
指针或引用对象的地址。如果该变量是局部变量,则每次调用该函数时,您可能会获得不同的地址。
您需要能够处理模板参数
template <std::string temp>
void f() {
// ...
}
f<"foo">();
f<"bar">(); // different function!?
现在,一个impl将需要为一个std::string
或任何其他由用户定义的任意类定义一个唯一的字符序列,并存储一个特定的值,其含义对于实现而言是未知的。另外,在编译时无法计算任意类对象的值。
计划考虑允许将文字类类型用作C ++ 0x后的模板参数类型,并通过常量表达式对其进行初始化。可以通过使数据成员根据其值递归地对其进行处理(例如,对于基类,我们可以应用深度优先,从左到右遍历)。但这绝对不适用于任意类。
模板参数列表中提供的非类型模板参数是一个表达式,其值可以在编译时确定。这样的论点必须是:
常量表达式,具有外部链接的函数或对象的地址或静态类成员的地址。
另外,字符串文字是具有内部链接的对象,因此您不能将它们用作模板参数。您也不能使用全局指针。考虑到四舍五入错误的明显可能性,不允许使用浮点文字。