我正在尝试使用默认指针类型创建参数包:
template<int*... T>
void f() {}
此代码出现错误:
int main(){
int* a = new int(5);
f<a>();
}
但是,如果我这样做,我不会收到错误消息:
int main(){
f<nullptr>();
}
为什么?
错误:
./example.cpp: In function 'int main()': ./example.cpp:6:7: error: the
value of 'a' is not usable in a constant expression
f<a>();
^ ./example.cpp:5:10: note: 'a' was not declared 'constexpr'
int* a = new int;
^ ./example.cpp:6:10: error: no matching function for call to 'f<a>()'
f<a>();
^ ./example.cpp:2:6: note: candidate: 'template<int* ...T> void f()' void f() {}
^ ./example.cpp:2:6: note: template argument deduction/substitution failed: ./example.cpp:6:10: error: 'a' is not a
valid template argument because 'a' is a variable, not the address of
a variable
f<a>();
^ Compiler returned: 1
答案 0 :(得分:3)
非类型模板参数的参数必须为constant expression。
int* a = new int(5);
在此代码段中,a
不是常量表达式,也不适合模板非类型参数。
事实上,这在直觉上应该是可以接受的。请记住,编译器需要在执行程序之前为实例化的模板生成代码,并且此代码必须使用template参数的值。但是a
的值在编译时未知-它可以是任何值,具体取决于将在何处分配内存。显然,编译器无法预测它的值。
另一方面,全局(或函数静态)对象的地址可用作非类型指针模板参数:
int k = 10;
int main(){
f<&k>();
}
上面的代码可以正常工作,因为编译器会知道全局对象所在的位置(编译器会将它自己放在这里!)
最后但并非最不重要的是,您的标题没有必要缩小。这些规则同样适用于非可变模板。