模板编译错误-标准与否

Template compilation error - standard or not?

本文关键字:标准 错误 编译      更新时间:2023-10-16

我有以下代码:

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

不编译,但如果我声明kconst,它可以编译:

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的情况下…对吧?

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

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

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

错误:' k '不能出现在常量表达式

§14.3.2.1(简略)说:

非类型、非模板模板形参的模板实参必须是:
-整型或枚举型的整型常量表达式;

§5.19.1说[删节,强调我的]:

整型常量表达式只能包含字面值、枚举数、const变量或用常量表达式…初始化的整型或枚举类型的静态数据成员。

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

这个错误有点误导人,因为"局部变量不能用作非类型参数"通常是正确的,但在某些限制下,它是完全正确的

No。当编译器试图将模板展开为最终形式时,可以在编译时计算Const值。所以执行时的值不能作为模板的参数,但是你总是可以将变量的引用设置为模板参数

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