以下代码与Intel-2015编译正常,但与gcc 4.8.3失败 谁是对的?
#include <iostream>
void f( int const& x ) { std::cout << x << std::endl; }
struct S
{
static constexpr int ce = 42;
};
int main()
{
f(S::ce);
return 0;
}
g ++错误:
/tmp/ccOIxa2V.o: In function `main':
test_constexpr.cpp:(.text+0x36): undefined reference to `S::ce'
collect2: error: ld returned 1 exit status
答案 0 :(得分:4)
我认为海湾合作委员会是对的。 BTW,CLang 3.5.1给出了同样的错误。
事情是,只有在不采用地址并且它们没有绑定到引用的情况下,才允许不定义常量静态变量。
您的示例绑定了对它的引用,因此需要显式定义。
从C ++ 11草案(9.4.2.3),方便编辑:
可以使用constexpr说明符在类定义中声明文字类型的静态数据成员; [...]如果在程序[...]中使用了odr-used(3.2),该成员仍应在命名空间范围内定义。
在3.2:
其名称显示为潜在评估表达式的变量[...]除非是满足出现在常量表达式(5.19)和左值到右值转换中的要求的对象,否则使用odr 4.1)立即应用。
粗略地说,每次使用变量时都会执行左值到右值的转换,除非将引用或参数绑定到一元接收地址运算符&
。
答案 1 :(得分:4)
因为函数f
采用引用参数,所以引用可以在运行时指向S::ce
的定义;编译器不能只用文字42替换参数。所以你必须添加一个类外定义:
const int S::ce;
就像使用非constexpr
变量一样。这会在运行时为值分配一个内存位置,供引用和在编译时无法计算的其他内容使用。
有关详细信息,请参阅this GCC bug report(其中的评论解释了为什么它实际上不是错误)。