std :: chrono :: duration :: duration()如何成为constexpr?

Bra*_*cer 17 c++ c++11 c++-chrono

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

constexpr duration() = default;

(例如,请参阅cppreference.com或libstdc ++源代码.)

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

constexpr构造函数必须满足以下要求:

...

必须在构造函数初始化列表中或通过成员大括号或相等的初始化程序初始化每个基类和每个非静态成员.另外,所涉及的每个构造函数都必须是constexpr构造函数,并且每个大括号或者相等的初始化程序的每个子句都必须是一个常量表达式

如果我对默认构造函数感到困惑,cppreference.com似乎说默认的构造函数与= default隐式构造函数的定义不同.

然而,rep(大多数)持续时间的类型是裸整数类型.所以,不应该将显式= default默认构造函数duration等效于

constexpr duration() {}

当然会保留duration::rep 未初始化类型的整数成员变量?而且,事实上,是不是标准的行为duration,使得缺省构造的值未初始化?(但我找不到明确说明这一点的参考文献.)

在那么如何才能= default为构造durationconstexpr,如果离开一个非静态成员变量初始化?我错过了什么?

How*_*ant 12

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

constexpr构造函数的定义应满足以下要求:

  • 班级不得有任何虚拟基类;
  • 对于默认的复制/移动构造函数,该类不应具有作为变体成员的可变子对象;
  • 每个参数类型应为文字类型;
  • 它的功能体不应该是功能试块;

此外,其功能体应为=删除,或者它应满足以下要求:

  • 其函数体应为= default,或其函数体的复合语句应满足constexpr函数的函数体的要求;
  • 应初始化每个非变量非静态数据成员和基类子对象(12.6.2);
  • 如果该类是具有变体成员的联合(9.5),则其中一个应该被初始化;
  • 如果类是类似联合的类,但不是联合,对于每个具有变体成员的匿名联合成员,其中只有一个应该被初始化;
  • 对于非委托构造函数,选择初始化非静态数据成员和基类子对象的每个构造函数都应该是constexpr构造函数;
  • 对于委托构造函数,目标构造函数应该是constexpr构造函数.

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

那么这如何与未初始化的结构一起工作呢?

它没有.

例如:

constexpr seconds x1{};
Run Code Online (Sandbox Code Playgroud)

以上工作并初始化x10s.然而:

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.
Run Code Online (Sandbox Code Playgroud)

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

完整的工作演示:

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


int
main()
{
    constexpr my_duration<int> x{};
}
Run Code Online (Sandbox Code Playgroud)

有趣的侧边栏

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

我一直在想为什么以下不起作用:

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;
        ^
Run Code Online (Sandbox Code Playgroud)

为什么让这个类成为非模板打破constexpr默认构造函数?!

然后我尝试了这个:

using Rep = int;

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


int
main()
{
    constexpr my_duration x{};
}
Run Code Online (Sandbox Code Playgroud)

编译器再次喜欢它.

如果还没有CWG问题,可能应该有.这种行为似乎有些不一致.这可能只是因为我们(整个行业)仍在学习constexpr.