我有以下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编译并链接此代码。另一方面,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)
哪个是对的?这段代码是否合法?我对静态constexpr成员的规则的理解(主要基于this question)是只有在获取变量的地址时才需要一个类外定义。但是我没有在任何地方获取Derived :: info的地址或使用它的引用;我只是按值将它传递给Base构造函数。
我发现了各种解决方法:
Base ({"Foobar", 2})
。这个解决方案可行,但随着更多成员被添加到struct Info中,它会变得很丑陋(在我看来)。答案 0 :(得分:2)
啊哈,似乎问题是隐式Info(const Info &)
复制构造函数。要将const Info &
引用传递给该构造函数,必须获取Derived :: info的地址。
显然,GCC在优化复制构造函数方面比Clang更具攻击性。如果我使用-fno-elide-constructors
,那么GCC也会抱怨对Derived :: info的未定义引用。
在任何情况下,将Base和Derived构造函数声明为constexpr似乎完成了我想要在这里发生的事情,即在编译时初始化Base :: info,而不是在运行时从单独的Derived :: info复制时间。