[英]When does a static constexpr class member need an out-of-class definition?
I have the following C++11 code (simplified version): 我有以下C ++ 11代码(简化版):
struct Info
{
const char * name;
int version;
};
class Base
{
public:
const Info info;
Base (Info info) : info (info) {}
};
class Derived : public Base
{
public:
static constexpr Info info = {"Foobar", 2};
Derived () : Base (info) {}
};
int main ()
{
static Derived derived;
return 0;
}
GCC 4.9.1 compiles and links this code fine. GCC 4.9.1编译并链接此代码很好。 Clang 3.5.0, on the other hand, complains about an undefined reference:
另一方面,Clang 3.5.0抱怨未定义的引用:
/tmp/test-109c5c.o: In function `main':
test.cc:(.text+0x1c): undefined reference to `Derived::info'
test.cc:(.text+0x22): undefined reference to `Derived::info'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Which is right? 哪个是对的? Is this code legal or not?
此代码合法吗? My understanding of the rules regarding static constexpr members (based mostly on this question ) is that an out-of-class definition is needed only when the address of the variable is taken.
我对有关静态constexpr成员的规则的理解(主要基于此问题 )是,仅当获取变量的地址时才需要类外定义。 But I'm not taking the address of Derived::info or using a reference to it anywhere;
但是我没有使用Derived :: info的地址,也没有在任何地方使用对它的引用。 I'm only passing it by value to the Base constructor.
我只是按值将其传递给Base构造函数。
Various workarounds that I've found: 我发现了各种解决方法:
Base ({"Foobar", 2})
. Base ({"Foobar", 2})
来调用Base构造函数。 This solution would work, but it gets ugly (in my opinion) as more members are added to struct Info. Aha, it seems that the problem is the implicit Info(const Info &)
copy constructor. 啊哈,看来问题出在隐式的
Info(const Info &)
复制构造函数。 To pass the const Info &
reference to that constructor, it's necessary to take the address of Derived::info. 要将
const Info &
引用传递给该构造函数,必须获取Derived :: info的地址。
Apparently GCC is more aggressive than Clang in optimizing away the copy constructor. 显然,在优化复制构造函数方面,GCC比Clang更具攻击性。 If I use
-fno-elide-constructors
, then GCC also complains about an undefined reference to Derived::info. 如果我使用
-fno-elide-constructors
,那么GCC也会抱怨对Derived :: info的未定义引用。
In any case, declaring the Base and Derived constructors as constexpr seems to accomplish what I want to happen here, which is to have Base::info initialized at compile time, rather than copied from a separate Derived::info at run time. 无论如何,将Base和Derived构造函数声明为constexpr似乎可以完成我想在这里完成的工作,即在编译时初始化Base :: info,而不是在运行时从单独的Derived :: info复制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.