c++ - 静态 constexpr 类成员何时需要类外定义?

标签 c++ c++11 plugins constexpr

我有以下 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 提示 undefined reference :

/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 和 Derived)都成为 constexpr。这可能是也可能不是真实类的选项,它们比示例中的类更复杂。无论如何,我要试试。
  • 在 main 中使用自动而非静态持续时间声明 Derived 的实例。这不是实际项目的选项:Derived 类是一个插件实现,它的一个实例需要作为共享对象中的公共(public)符号导出。
  • 完全删除 Derived::info 并使用大括号初始化的临时对象调用 Base 构造函数,即 Base ({"Foobar", 2})。这个解决方案可行,但随着更多成员被添加到结构信息中,它变得丑陋(在我看来)。

最佳答案

啊哈,问题似乎出在隐式 Info(const Info &) 复制构造函数上。要将 const Info & 引用传递给该构造函数,必须获取 Derived::info 的地址。

显然,GCC 在优化复制构造函数方面比 Clang 更积极。如果我使用 -fno-elide-constructors,那么 GCC 也会提示对 Derived::info 的 undefined reference 。

在任何情况下,将 Base 和 Derived 构造函数声明为 constexpr 似乎可以完成我想在这里发生的事情,即在编译时初始化 Base::info,而不是在运行时从单独的 Derived::info 复制时间。

关于c++ - 静态 constexpr 类成员何时需要类外定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26077703/

相关文章:

c# - 无法将 C++ 中的 TextBox_TextChanged() 转换为 C#

c++ - 重载运算符 >>

c++ - 来自函数参数的容器的 decltype

c++ - 有条件地替换字符串中的正则表达式匹配

c++ - 2012 年 1 月 C++11 工作草案 "Source"格式?

php - 如何从 WordPress 中的插件 php 编辑 mySQL wp_posts 表?

php - Joomla 3.3 - 通过插件向所有菜单项添加自定义字段 - 参数未保存

c++ - 为什么 std::vector of boost::variant 在 boost spirit 中导致解析问题?

C++ - JSON::Value 在函数参数中用作引用