Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板编译错误-是否标准?_C++_Templates - Fatal编程技术网

C++ 模板编译错误-是否标准?

C++ 模板编译错误-是否标准?,c++,templates,C++,Templates,我有以下代码: template<int k> void foo() { } int main(int argc, char* argv[]) { int k = 1000; foo<k>(); return 0; } 现在,我明白了为什么在第一种情况下它不编译,在第二种情况下它编译,但这是由标准指定的吗 我得到的错误是: Error 1 error C2971: 'foo' : template parameter 'k' : 'k'

我有以下代码:

template<int k>
void foo()
{
}
int main(int argc, char* argv[])
{
    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
的情况下。。。对吗?

根据标准14.3.2,这必须是一个常量表达式:

非类型、非模板模板参数的模板参数应为以下参数之一:
-整数或枚举类型的整数常量表达式;或
-非类型模板参数的名称;或
-具有外部链接的对象或函数的地址,包括函数模板和函数模板id,但不包括非静态类成员,表示为&id表达式,如果名称引用函数或数组,或者如果相应的模板参数是引用,则&id是可选的; 或
-指向构件的指针,如5.3.1所述

GCC 4.6.2给出了一个稍微更容易理解的错误:

错误:“k”不能出现在常量表达式中


不可以。当编译器尝试将模板扩展为最终形式时,可以在编译时计算常量值。所以执行时间值不能作为模板的参数,但始终可以将对变量的引用设置为模板参数

template<int& k>
void foo()
{
}
int main(int argc, char* argv[])
{
    int k = 1000;
    foo<k>();
    return 0;
}
模板
void foo()
{
}
int main(int argc,char*argv[])
{
int k=1000;
foo();
返回0;
}

§14.3.2.1说[节略]:

非类型、非模板模板参数的模板参数应为以下参数之一:
-整型或枚举型的整型常量表达式

而§5.19.1中说[节略,强调我的]:

整型常量表达式只能涉及用常量表达式初始化的整型或枚举类型的文本、枚举数、常量变量或静态数据成员

k
的第二个定义满足这一点,因此允许将其用作模板参数的ICE


这个错误有点误导性,因为“局部变量不能用作非类型参数”通常是正确的,但有一些限制,这是完全正确的。

您没有说明为什么
k
在一个变量中有效,而在另一个变量中无效,这是问题的核心。请参阅我用粗体显示的部分。标准上说表达式必须是常数。但我重复我自己的话:你不能解释为什么
k
可用或不可用。我可以向你解释,但我不能为你理解。我不知道怎样才能把事情说得更清楚。这是因为标准规定表达式必须是常数。如果你真的认为这一点不完全明显,那么你的答案是完整的,我的答案不是。老实说,我认为这是不必要的混乱。
template<int& k>
void foo()
{
}
int main(int argc, char* argv[])
{
    int k = 1000;
    foo<k>();
    return 0;
}