如何才能成为constexpr

如何才能成为constexpr

本文介绍了std :: chrono :: duration :: duration()如何才能成为constexpr?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

std :: chrono :: duration 的默认构造函数定义如下:

The default constructor of std::chrono::duration is defined as follows:

constexpr duration()=默认值;

(例如,请参见 cppreference.com 或libstdc ++源)

(For example, see cppreference.com or the libstdc++ source.)

但是, cppreference.com也对 constexpr 构造函数:

...

每个基类和每个非静态成员都必须初始化,无论是在构造函数初始化列表中,还是在成员大括号或相等初始化器中.此外,涉及的每个构造函数都必须是constexpr构造函数,每个大括号或相等的初始化程序的每个子句都必须是一个常量表达式

every base class and every non-static member must be initialized, either in the constructors initialization list or by a member brace-or-equal initializer. In addition, every constructor involved must be a constexpr constructor and every clause of every brace-or-equal initializer must be a constant expression

如果我对默认构造函数感到困惑,则 cppreference.com似乎会说 = default 结合使用的默认构造函数的定义与隐式默认构造函数的定义没有不同.

And in case I was confused about default constructors, cppreference.com seems to say that default constructors brought into being with = default aren't defined differently than implicit default constructors.

但是, rep 类型在(大多数)持续时间内是一个裸整数类型.因此, duration 的显式 = default 默认构造函数不应等效于

Yet, the rep type for (most) durations is a bare integer type. So, shouldn't the explicit = default default constructor for duration be equivalent to

constexpr duration(){}

哪个会保留未初始化 duration :: rep 类型的整数成员变量?而且,实际上, duration 的标准行为不是未初始化默认构造的值 的行为吗?(但我找不到明确说明这一点的参考.)

which of course would leave the integer member variable of type duration::rep uninitialized? And, in fact, isn't the standard behaviour of duration such that default-constructed values are uninitialized? (But I can't find a reference that explicitly says this.)

那么如果 duration = default 构造函数如果未初始化非静态成员变量,怎么能成为 constexpr ?我想念什么?

So how can the = default constructor for duration be constexpr if it leaves a non-static member variable uninitialized? What am I missing?

推荐答案

7.1.5 constexpr 说明符[dcl.constexpr]说:

7.1.5 The constexpr specifier [dcl.constexpr] says:

  • 该类不应具有任何虚拟基类;
  • 对于默认的复制/移动构造函数,该类不应具有作为变体成员的可变子对象;
  • 每种参数类型应为文字类型;
  • 其功能主体不得为function-try-block;

此外,其功能主体应为= delete,或者应为满足以下要求:

In addition, either its function-body shall be = delete, or it shall satisfy the following requirements:

  • 其功能主体应为=默认值,或其功能主体的复合声明应满足要求用于constexpr函数的函数体;
  • 每个不变的非静态数据成员和基类子对象都应初始化(12.6.2);
  • 如果该类是具有变体成员(9.5)的联合,则应精确地初始化其中之一;
  • 如果该类是类似联合的类,但不是联合,则对于其每个具有变体成员的匿名联合成员,正好是它们应该被初始化;
  • 对于非委托的构造函数,选择用来初始化非静态数据成员和基类子对象的每个构造函数应为constexpr构造函数;
  • 对于委托的构造函数,目标构造函数应为constexpr构造函数.

简而言之,只要满足上述其他要求, = default constexpr 默认构造函数的有效定义.

In a nutshell, = default is a valid definition of a constexpr default constructor as long as the other requirements above are met.

那么这对未初始化构造如何起作用?

So how does this work with uninitialized constructions?

不是.

例如:

constexpr seconds x1{};

上面的方法可以将 x1 初始化为 0s .但是:

The above works and initializes x1 to 0s. However:

constexpr seconds x2;

error: default initialization of an object of const type 'const seconds'
       (aka 'const duration<long long>') without a user-provided default
        constructor
    constexpr seconds x2;
                      ^
                        {}
1 error generated.

因此,要创建默认构造的 duration constexpr ,必须对其进行零初始化.并且 = default 实现允许使用 {} 进行零初始化.

So to create a constexpr default constructed duration, you must zero-initialize it. And the = default implementation allows one to zero-initialize with the {}.

完整的工作演示:

template <class Rep>
class my_duration
{
    Rep rep_;
public:
    constexpr my_duration() = default;
};


int
main()
{
    constexpr my_duration<int> x{};
}

有趣的侧边栏

我在编写此答案时学到了一些东西,并希望分享:

I learned something in writing this answer, and wanted to share:

我一直想知道为什么以下方法不起作用:

I kept wondering why the following doesn't work:

using Rep = int;

class my_duration
{
    Rep rep_;
public:
    constexpr my_duration() = default;
};


int
main()
{
    constexpr my_duration x{};
}

error: defaulted definition of default constructor is not constexpr
        constexpr my_duration() = default;
        ^

为什么将此类设为非模板会破坏 constexpr 默认构造函数?!

Why does making this class a non-template break the constexpr default constructor?!

然后我尝试了这个:

using Rep = int;

class my_duration
{
    Rep rep_;
public:
    my_duration() = default;  // removed constexpr
};


int
main()
{
    constexpr my_duration x{};
}

然后编译器再次喜欢它.

And the compilers like it again.

如果对此尚无CWG问题,则可能应该存在.行为似乎有点不一致.这可能只是因为我们(整个行业)仍在学习 constexpr .

If there isn't already a CWG issue on this, there probably should be. The behavior seems a bit inconsistent. And this is probably just because we (the entire industry) are still learning about constexpr.

这篇关于std :: chrono :: duration :: duration()如何才能成为constexpr?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 10:34