静态constexpr类成员何时需要类外定义
When does a static constexpr class member need an out-of-class definition?
我有以下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成员的规则的理解(主要基于这个问题)是,只有当获取变量的地址时,才需要类外定义。但我不会使用Derived::info的地址,也不会在任何地方引用它;我只是通过值将它传递给Base构造函数。
我发现的各种解决方法:
- 使两个构造函数(Base和Derived)都为constexpr。这可能是真实类的选项,也可能不是,真实类比示例中的类更复杂。不管怎样,我还是要试试
- 用自动而非静态持续时间在main中声明Derived的实例。这不是真正项目的选项:Derived类是一个插件实现,它的一个实例需要作为共享对象中的公共符号导出
- 完全移除Derived::info,并使用大括号初始化的临时对象(即
Base ({"Foobar", 2})
)调用Base构造函数。这个解决方案是可行的,但随着更多成员被添加到structInfo中,它变得很难看(在我看来)
Aha,问题似乎是隐式Info(const Info &)
复制构造函数。要将const Info &
引用传递给该构造函数,需要获取Derived::info的地址。
显然,GCC在优化副本构造函数方面比Clang更积极。如果我使用-fno-elide-constructors
,那么GCC还会抱怨对Derived::info的未定义引用。
在任何情况下,将Base和Derived构造函数声明为constexpr似乎可以实现我想要实现的目标,即在编译时初始化Base::info,而不是在运行时从单独的Derive::info复制。
相关文章:
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- C++令牌定义成员
- 在没有类定义的标头中定义成员变量
- 如何在类的构造函数中定义成员向量的大小
- 如何在C++中动态定义成员函数
- C++ Boost.Serialization - 用户定义成员的非侵入式序列化
- C++类 - 使用公共变量并在类外定义成员函数
- G++ - 对已定义成员函数的未定义引用
- 在哪里以及如何定义成员变量?在头文件还是实现文件中?
- 是否可以修改STL并自定义成员函数
- 从 boost::mpl:vector 类型列表中定义成员变量
- 在构造对象时定义成员函数
- 为什么定义成员函数指针变量需要类名
- 复制构造函数中的 C++ 用户定义成员
- 如何根据类参数定义成员类运算符
- 使用指向未定义成员函数的指针时的未定义引用
- 如何在运行时定义成员数组大小
- C++-在模板类之外但在头中定义成员函数
- c++在不知道对象类型的情况下定义成员函数指针
- 在特定偏移量中定义成员的结构