简体   繁体   English

为什么 constexpr 静态成员(类型类)需要定义?

[英]Why does constexpr static member (of type class) require a definition?

==> See the full snippet code and compilation on coliru . ==> 在coliru上查看完整的代码片段和编译。

I have a LiteralType class filling constexpr requirements :我有一个LiteralType类填充constexpr要求

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;
};

I use it as a constexpr static member variable:我将它用作constexpr static成员变量:

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

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

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

But the linker says:但是链接器说:
(Clang-3.5 and GCC-4.9) (Clang-3.5 和 GCC-4.9)

undefined reference to `Foo::str_'

I have to define the constexpr static member!我必须定义constexpr static成员!
(I do not specify the constructor parameters) (我没有指定构造函数参数)

constexpr MyString Foo::str_;

However if the constexpr static member had been an int the member would not have to be defined outside the class definition.但是,如果constexpr static成员是int则不必在类定义之外定义该成员。 This is my understanding, but I am not sure...这是我的理解,但我不确定...

Questions:问题:

  • Why int does not need to be defined outside the class declaration but MyString requires this?为什么int不需要在类声明之外定义,但MyString需要这个?
  • Is there a disadvantage to define a constexpr static member in a header file?在头文件中定义constexpr static成员是否有缺点?
    (I provide my library as header files only) (我只提供我的库作为头文件)

The One Definition rule tells us that we can not have more than one definition of an odr-used variable in a program.单一定义规则告诉我们,在一个程序中,一个odr-used变量的定义不能超过一个。 So if a variable is odr-used then you need to define it but you can not define it the header file since it may be included more than once with the whole program.所以如果一个变量是 odr-used 那么你需要定义它,但你不能定义它的头文件,因为它可能被包含在整个程序中不止一次。 Odr-use violations do not require a diagnostic message and so you can violate this rule and the compiler is not obliged to notify you. Odr 使用违规不需要诊断消息,因此您可以违反此规则,编译器没有义务通知您。

In your case you are indeed odr-using str_ , and you can not include the definition in the header file because that would violate the one definiton rule since it can be included more than once within the program.在您的情况下,您确实是使用 odr 的str_ ,并且您不能在头文件中包含该定义,因为这将违反一个定义规则,因为它可以在程序中多次包含。

It is interesting to note that if you had done the following it would not have been odr-used:有趣的是,如果您执行了以下操作,则不会使用 odr:

return str_.size_;

You would therefore not need to define the variable, which can have some odd consequences in some examples .因此,您不需要定义变量,这在某些示例中可能会产生一些奇怪的后果 I doubt that really solves your problem long-term.我怀疑这是否真的能长期解决你的问题。

The odr rules are covered in the draft C++ standard section 3.2 and they say: odr 规则包含在 C++ 标准草案第3.2节中,他们说:

A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression (Clause 5).变量 x 其名称显示为潜在求值表达式 ex 是 odr-used 除非将左值到右值转换 (4.1) 应用到 x 产生一个不调用任何非平凡函数的常量表达式 (5.19) 并且,如果x 是一个对象,ex 是表达式 e 的潜在结果集合中的一个元素,其中左值到右值的转换(4.1)应用于 e,或者 e 是丢弃值表达式(第 5 条)。 this is odr-used if it appears as a potentially-evaluated expression (including as the result of the implicit transformation in the body of a non-static member function (9.3.1)).[...]如果它作为潜在评估的表达式出现(包括作为非静态成员函数 (9.3.1) 的主体中的隐式转换的结果),则 this 被使用。[...]

So str_ yield a constant expression, the lvalue-to-rvalue conversion is not applied the expression str_.size() and it is not a discarded value expression, so it is odr-used and therefore str_ is required to be defined.所以str_产生一个常量表达式,左值到右值的转换没有应用表达式str_.size()并且它不是丢弃值表达式,因此它是 odr-used ,因此需要定义str_

On the other hand the lvalue-to-rvalue conversion is applied to the expression str_.size_ , so it is not odr-used and does not require str_ to be defined.另一方面,左值到右值的转换应用于表达式str_.size_ ,因此它不是 odr 使用的,也不需要定义str_

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么GCC认为constexpr静态数据成员的定义必须标记为constexpr? - Why does GCC think that the definition of a constexpr static data member must be marked constexpr? 为什么编译器在已经具有类资格的成员函数定义的返回类型上要求类限定符? - Why does the compiler require the class qualifier on the return type of an already class-qualified member function definition? 为什么成员 function 不能要求同一个 class 的 static constexpr 成员为真? - Why can't a member function require a static constexpr member of the same class to be true? 静态constexpr类成员何时需要类外定义? - When does a static constexpr class member need an out-of-class definition? 静态类成员的初始化。 为什么用constexpr? - Initialisation of static class member. Why constexpr? 与定义的类相同类型的静态constexpr成员 - static constexpr member of same type as class being defined 是否可以使用模板 class X 的 X 类型的 static constexpr 成员? - Is it possible to have a static constexpr member with type X of template class X? 定义一个 static 同类型模板 class 的 constexpr 成员 - Define a static constexpr member of same type of a template class 添加静态constexpr成员是否会更改结构/类的内存映射? - Does adding a static constexpr member change the memory mapping of a struct/class? 静态constexpr成员的is_specialization类型特征 - is_specialization type trait for a static constexpr member
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM