为什么constexpr静态成员(类型类)需要定义? [英] Why does constexpr static member (of type class) require a definition?

查看:80
本文介绍了为什么constexpr静态成员(类型类)需要定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

==>参见 coliru 上的完整代码段和编译。

==> See the full snippet code and compilation on coliru.

我有一个 LiteralType 类满足 constexpr 的要求

I have a LiteralType class filling 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静态 成员变量:

I use it as a constexpr static member variable:

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静态成员是否 int 成员不必在类定义之外进行定义。这是我的理解,但我不确定...

However if the constexpr static member had been an int the member would not have to be defined outside the class definition. This is my understanding, but I am not sure...


  • 为什么 int 不需要在类声明之外定义,但是 MyString 要求这样做吗?

  • 在头文件中定义 constexpr静态成员是否有缺点?
    (我仅将库作为头文件提供)

  • Why int does not need to be defined outside the class declaration but MyString requires this?
  • Is there a disadvantage to define a constexpr static member in a header file?
    (I provide my library as header files only)

推荐答案

一个定义规则告诉我们,一个 odr用过的变量。因此,如果使用了odr变量,则需要定义它,但不能将其定义为头文件,因为在整个程序中它可能不只包含一次。违反Odr用法不需要​​诊断消息,因此您可以违反此规则,并且编译器没有义务通知您。

The One Definition rule tells us that we can not have more than one definition of an odr-used variable in a program. 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-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-使用 str _ ,并且您不能在头文件中包含该定义,因为这会违反一个定义规则,因为它可以在程序中多次包含。

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.

有趣的是,如果您执行了以下操作,则不会被过度使用:

It is interesting to note that if you had done the following it would not have been odr-used:

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.

C ++标准草案 3.2 并且他们说:

The odr rules are covered in the draft C++ standard section 3.2 and they say:


变量x其名称显示为可能评估的表达式
ex除非被应用,否则会被过度使用从左值到右值的转换(4.1)
到x产生一个常量表达式(5.19),该表达式不调用任何
非平凡函数,并且如果x是对象,则ex是该元素的元素
表达式e的一组潜在结果,其中
左值到右值转换(4.1)应用于e,或者e是
废弃值表达式(第5条) 。如果它看起来像
作为可能评估的表达式(包括作为非静态成员函数
(9.3.1)的主体中
隐式转换的结果),则将使用此方法。 )。[...]

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). 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)).[...]

所以 str _ 产生一个常数表达式,左值到右值的转换未应用表达式 str_.size(),并且它不是舍弃的值表达式,因此它已被odr使用,因此<$ c必须定义$ c> str _

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_.size _ ,因此它不被使用,并且不需要定义 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.

这篇关于为什么constexpr静态成员(类型类)需要定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆