提问人:Luchian Grigore 提问时间:11/23/2011 更新时间:11/23/2011 访问量:1008
模板编译错误 - 标准与否?
Template compilation error - standard or not?
问:
我有以下代码:
template<int k>
void foo()
{
}
int main(int argc, char* argv[])
{
int k = 1000;
foo<k>();
return 0;
}
它不会编译,但是如果我声明为 ,它会:k
const
template<int k>
void foo()
{
}
int main(int argc, char* argv[])
{
const int k = 1000;
foo<k>();
return 0;
}
现在,我明白了为什么在第一种情况下它不编译而在第二种情况下它能编译,但这是标准规定的吗?
我得到的错误是:
Error 1 error C2971: 'foo' : template parameter 'k' : 'k' : a local variable cannot be used as a non-type argument
这并不完全清楚,因为也是一个局部变量,在这种情况下它是......右?k
const
答:
4赞
David Schwartz
11/23/2011
#1
根据标准 14.3.2,这必须是一个常量表达式:
非类型、非模板模板参数的模板参数应为以下参数之一:
— 整数或枚举类型的整数常量表达式;或
— 非类型模板参数的名称;或者
— 具有外部链接的对象或函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示为 & id-expression,其中 & 如果名称引用函数或数组,或者相应的模板参数是引用,则 & 是可选的; 或
— 指向成员的指针,如 5.3.1 中所述。
GCC 4.6.2 给出了一个稍微容易理解的错误:
错误:“k”不能出现在常量表达式中
评论
0赞
GManNickG
11/23/2011
你没有具体说明为什么在一个中有效,而在另一个中不起作用,这是问题的核心。k
0赞
David Schwartz
11/23/2011
请参阅我加粗的部分。标准规定表达式必须是常数。
0赞
GManNickG
11/23/2011
但我再说一遍:你没有解决为什么可用或不可用。k
0赞
David Schwartz
11/23/2011
我可以向你解释,但我无法为你理解。我不知道我怎样才能把它说得比我现在更清楚。这是因为标准说表达式必须是常数。
1赞
David Schwartz
11/23/2011
如果你真的认为这一点并不完全明显,那么你的答案是完整的,而我的答案不是。 老实说,我认为这是不必要的混乱。
2赞
Hauleth
11/23/2011
#2
不。当编译器尝试将模板扩展为最终形式时,可以在编译时计算 Const 值。因此,执行时值不能是模板的参数,但始终可以将对变量的引用设置为模板参数
template<int& k>
void foo()
{
}
int main(int argc, char* argv[])
{
int k = 1000;
foo<k>();
return 0;
}
2赞
GManNickG
11/23/2011
#3
§14.3.2.1 说 [删节]:
非类型、非模板模板参数的模板参数应为以下参数之一:
— 整数或枚举类型的整数常量表达式;
§5.19.1 说 [删节,强调我的]:
整型常量表达式只能涉及使用常量表达式初始化的整型或枚举类型的文字、枚举器、常量变量或静态数据成员...
您的第二个定义满足了这一点,因此允许将其用作模板参数的 ICE。k
这个错误有点误导,因为“局部变量不能用作非类型参数”通常是正确的,但有一定的限制,它完全没问题。
评论