【问题标题】:Why does constexpr static member (of type class) require a definition?为什么 constexpr 静态成员(类型类)需要定义?
【发布时间】:2015-04-01 18:13:08
【问题描述】:

==> 在coliru 上查看完整的 sn-p 代码和编译。

我有一个LiteralType 类填充constexpr requirements

struct MyString
{
    constexpr MyString(char const* p, int s) : ptr(p), sz(s) {}
    constexpr char const* data() const { return ptr; }
    constexpr int         size() const { return sz;  }

    char const *ptr = 0;
    int  const  sz  = 0;
};

我将它用作constexpr static 成员变量:

struct Foo
{
    int size() { return str_.size(); }

    constexpr static MyString str_{"ABC",3};
};

int main()
{
  Foo foo;
  return ! foo.size();
}

但链接器说:
(Clang-3.5 和 GCC-4.9)

undefined reference to `Foo::str_'

我要定义constexpr static成员!
(我没有指定构造函数参数)

constexpr MyString Foo::str_;

但是,如果 constexpr static 成员是 int,则不必在类定义之外定义该成员。这是我的理解,但我不确定……

问题:

  • 为什么int 不需要在类声明之外定义,而MyString 需要这个?
  • 在头文件中定义constexpr static 成员是否有缺点?
    (我只提供我的库作为头文件)

【问题讨论】:

  • 感谢@ShafikYaghmour 的链接。我不知道odr-used。请您在答案中提供更多信息。您还可以解释是否建议在头文件中定义成员...干杯
  • static const int 在 c++11 之前就已经是特殊情况了。即使那样,如果您需要静态 const int 的地址,除了声明之外,您还必须提供定义。
  • 完美@DaleWilson 我理解:-) 但是我是否还必须在我的库中提供一个“.cpp”文件?

标签: c++ c++11 static-members c++14 constexpr


【解决方案1】:

One Definition rule 告诉我们在程序中不能有多个odr-used 变量的定义。所以如果一个变量是 odr-used 那么你需要定义它,但你不能定义它的头文件,因为它可能被包含在整个程序中不止一次。 Odr 使用违规不需要诊断消息,因此您可以违反此规则,编译器没有义务通知您。

在您的情况下,您确实在使用 str_,并且您不能在头文件中包含该定义,因为这将违反一个定义规则,因为它可以在程序中多次包含。

有趣的是,如果您执行了以下操作,它将不会被 odr-used:

return str_.size_;

因此您不需要定义变量which can have some odd consequences in some examples。我怀疑这是否真的能长期解决您的问题。

C++ 标准草案3.2 中涵盖了 odr 规则,他们说:

变量 x,其名称显示为潜在求值表达式 除非应用左值到右值转换 (4.1),否则 ex 是 odr-used to x 产生一个不调用任何表达式的常量表达式 (5.19) 非平凡函数,如果 x 是一个对象,ex 是 表达式 e 的一组潜在结果,其中 左值到右值转换 (4.1) 应用于 e,或者 e 是 丢弃值表达式(第 5 条)。如果出现,这是 odr-used 作为潜在评估的表达式(包括作为 非静态成员函数体中的隐式转换 (9.3.1)).[...]

所以str_ 产生一个常量表达式,左值到右值的转换不适用于表达式str_.size() 并且它不是一个丢弃的值表达式,所以它是 odr-used 并且因此需要str_被定义。

另一方面,左值到右值的转换应用于表达式str_.size_,因此它不用于odr,也不需要定义str_

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多