C++ constexpr上的英特尔vs GCC
以下代码在Intel-2015中编译正常,但在gcc 4.8.3中编译失败 谁是对的C++ constexpr上的英特尔vs GCC,c++,gcc,intel,static-members,constexpr,C++,Gcc,Intel,Static Members,Constexpr,以下代码在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; } 我认为GCC是对的。顺便说
#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;
}
我认为GCC是对的。顺便说一句,Clang3.5.1给出了相同的错误 问题是,只有在不获取常量静态变量的地址并且它们不绑定到引用的情况下,才允许不定义常量静态变量 您的示例限制了对它的引用,因此需要显式定义 从C++11草案(9.4.2.3)中,方便地编辑: 可以使用constexpr说明符在类定义中声明文本类型的静态数据成员;[…]如果程序[…]中使用了odr(3.2),则仍应在命名空间范围中定义该成员 第3.2节: 除非变量[…]是满足常量表达式(5.19)中出现要求的对象,并且立即应用左值到右值的转换(4.1),否则将使用odr变量[…]
粗略地说,左值到右值的转换是在每次使用变量时完成的,除非将引用或作为参数绑定到一元take address运算符
&
,因为函数f
采用引用参数,必须有一个引用可以在运行时指向的S::ce
的定义;编译器不能仅仅用文字42替换参数。因此,您必须添加一个类外定义:
const int S::ce;
就像使用非constexpr
变量一样。这将在运行时为值分配一个内存位置,供引用和编译时无法计算的其他内容使用
有关更多信息,请参阅(其中有解释为什么它实际上不是一个bug的注释)。GCC是对的。使用
s.se
是正确的,但是std::cout
ce
是静态的,s::ce
是正确的。它与constexpr
@ForceBru有关,点运算符作用于对象,而不是类型。@user2052436,为什么u使用GCC而不是g++?那是C++,不是吗?都是对的。这是一个不需要诊断的ODR冲突代码>正如您所建议的,icc工作,而g++失败,出现错误:重新声明的S::ce'
。如果我添加constexpr int test::ce代码>,然后两者都能工作。哎呀,很抱歉测试::
这件事-我从测试程序中复制了代码,但实际上没有对照您的问题进行检查。但是constints::ce代码>为我工作;您不应该在类外定义中需要constexpr
。如果S::ce
声明为const
,则对我有效。但如果声明为constexpr
,则类外定义也必须是constexpr
。否则,icc和g++都会失败。也就是说,定义和声明必须完全匹配,不能在一个位置有const
,在另一个位置有constepr
。编译器版本是否不同?我们是否可以大胆地说,static
类内声明前面有一个隐式的extern
。
const int S::ce;