为什么使用局部变量作为非类型参数是非法的?
例如,在下一个代码local_var
中不能作为X
.
template<int& x> struct X {};
void f(int local_var)
{
X<local_var> x;
}
因为必须在编译时评估模板参数,并且编译器直到运行时才知道局部变量的地址(为了绑定对对象的引用,编译器需要知道该对象的地址)。
请注意,C++11 标准准确地说明了第 14.3.2/1 段中可以提供哪些非类型模板参数:
非类型、非模板模板参数的模板参数应为以下之一:
— 对于整数或枚举类型的非类型模板参数,模板参数类型的转换常量表达式(5.19);或者
— 非类型模板参数的名称;或者
— 一个常量表达式 (5.19),它指定具有静态存储持续时间和外部或内部链接的对象或具有外部或内部链接的函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示为 (忽略括号)作为 & id-expression,但如果名称引用函数或数组,则 & 可以省略,如果相应的模板参数是引用,则应省略;或者
— 一个常量表达式,计算结果为空指针值 (4.10);或者
— 一个常量表达式,其值为空成员指针值 (4.11);或者
— 一个指向成员的指针,如 5.3.1 所述;或者
— 类型的地址常量表达式
std::nullptr_t
。
如您所见,局部变量不在此列表中。
模板的“值”需要在编译时出现。
template<int x> struct X {};
即使您没有在此处绑定引用或传递指针,编译器也必须在编译时知道传递的元素的值。
替换int &x
为int x
这里是故意的。关于 int& 的东西得到了正确的回答。我只是想指出它适用于所有非类型化模板参数。
template<int*>
是一个地址......
X<local_var> x; // will not work, local_var does not exist at compile time
X<1> x; // works since 1 is known
我只是想(除了安迪的回答)阻止任何建议使用值类型而不是引用的结论。