std::chrono::duration::duration() 怎么可能是 constexpr?
How can std::chrono::duration::duration() be constexpr?
std::chrono::duration
的默认构造函数定义如下:
constexpr duration() = default;
(例如,参见 cppreference.com 或 libstdc++ 源代码。)
但是,cppreference.com also says this 关于 constexpr
个构造函数:
A constexpr constructor must satisfy the following requirements:
...
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 seems to say = default
带来的默认构造函数与隐式默认构造函数的定义没有区别。
然而,(大多数)持续时间的 rep
类型是裸整数类型。因此, duration
的显式 = default
默认构造函数不应该等同于
constexpr duration() {}
哪一个当然会让 duration::rep
类型的整型成员变量未初始化?而且,事实上,duration
的标准行为不就是默认构造的值 是 未初始化的吗? (但我找不到明确说明这一点的参考资料。)
那么,如果 duration
的 = default
构造函数让非静态成员变量未初始化,那么它怎么会是 constexpr
呢?我错过了什么?
7.1.5 constexpr
说明符 [dcl.constexpr] 表示:
The definition of a constexpr
constructor shall satisfy the
following requirements:
- the class shall not have any virtual base classes;
- for a defaulted copy/move constructor, the class shall not have a mutable subobject that is a variant member;
- each of the parameter types shall be a literal type;
- its function-body shall not be a function-try-block;
In addition, either its function-body shall be = delete, or it shall
satisfy the following requirements:
- either its function-body shall be = default, or the compound-statement of its function-body shall satisfy the requirements
for a function-body of a constexpr function;
- every non-variant non-static data member and base class sub-object shall be initialized (12.6.2);
- if the class is a union having variant members (9.5), exactly one of them shall be initialized;
- if the class is a union-like class, but is not a union, for each of its anonymous union members having variant members, exactly one of
them shall be initialized;
- for a non-delegating constructor, every constructor selected to initialize non-static data members and base class sub-objects shall be
a constexpr constructor;
- for a delegating constructor, the target constructor shall be a constexpr constructor.
简而言之,只要满足上述其他要求,= default
就是 constexpr
默认构造函数的有效定义。
那么这如何与 未初始化的 结构一起工作?
没有。
例如:
constexpr seconds x1{};
上面的工作并将 x1
初始化为 0s
。然而:
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.
因此,要创建一个 constexpr
默认构造的 duration
,您必须 零初始化 它。 = default
实现允许使用 {}
.
进行零初始化
完成工作演示:
template <class Rep>
class my_duration
{
Rep rep_;
public:
constexpr my_duration() = default;
};
int
main()
{
constexpr my_duration<int> x{};
}
有趣的边栏
我在写这个答案的过程中学到了一些东西,想分享一下:
我一直想知道为什么以下方法不起作用:
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;
^
为什么将此 class 设为非模板会破坏 constexpr
默认构造函数?!
(更新: 现在用 C++20 编译)
然后我试了这个:
using Rep = int;
class my_duration
{
Rep rep_;
public:
my_duration() = default; // removed constexpr
};
int
main()
{
constexpr my_duration x{};
}
编译器再次喜欢它。
如果还没有关于此的 CWG 问题,可能应该有。行为似乎有点不一致。这可能只是因为我们(整个行业)仍在学习 constexpr
. Fixed in C++20.
std::chrono::duration
的默认构造函数定义如下:
constexpr duration() = default;
(例如,参见 cppreference.com 或 libstdc++ 源代码。)
但是,cppreference.com also says this 关于 constexpr
个构造函数:
A constexpr constructor must satisfy the following requirements:
...
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 seems to say = default
带来的默认构造函数与隐式默认构造函数的定义没有区别。
然而,(大多数)持续时间的 rep
类型是裸整数类型。因此, duration
的显式 = default
默认构造函数不应该等同于
constexpr duration() {}
哪一个当然会让 duration::rep
类型的整型成员变量未初始化?而且,事实上,duration
的标准行为不就是默认构造的值 是 未初始化的吗? (但我找不到明确说明这一点的参考资料。)
那么,如果 duration
的 = default
构造函数让非静态成员变量未初始化,那么它怎么会是 constexpr
呢?我错过了什么?
7.1.5 constexpr
说明符 [dcl.constexpr] 表示:
The definition of a
constexpr
constructor shall satisfy the following requirements:
- the class shall not have any virtual base classes;
- for a defaulted copy/move constructor, the class shall not have a mutable subobject that is a variant member;
- each of the parameter types shall be a literal type;
- its function-body shall not be a function-try-block;
In addition, either its function-body shall be = delete, or it shall satisfy the following requirements:
- either its function-body shall be = default, or the compound-statement of its function-body shall satisfy the requirements for a function-body of a constexpr function;
- every non-variant non-static data member and base class sub-object shall be initialized (12.6.2);
- if the class is a union having variant members (9.5), exactly one of them shall be initialized;
- if the class is a union-like class, but is not a union, for each of its anonymous union members having variant members, exactly one of them shall be initialized;
- for a non-delegating constructor, every constructor selected to initialize non-static data members and base class sub-objects shall be a constexpr constructor;
- for a delegating constructor, the target constructor shall be a constexpr constructor.
简而言之,只要满足上述其他要求,= default
就是 constexpr
默认构造函数的有效定义。
那么这如何与 未初始化的 结构一起工作?
没有。
例如:
constexpr seconds x1{};
上面的工作并将 x1
初始化为 0s
。然而:
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.
因此,要创建一个 constexpr
默认构造的 duration
,您必须 零初始化 它。 = default
实现允许使用 {}
.
完成工作演示:
template <class Rep>
class my_duration
{
Rep rep_;
public:
constexpr my_duration() = default;
};
int
main()
{
constexpr my_duration<int> x{};
}
有趣的边栏
我在写这个答案的过程中学到了一些东西,想分享一下:
我一直想知道为什么以下方法不起作用:
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;
^
为什么将此 class 设为非模板会破坏 constexpr
默认构造函数?!
(更新: 现在用 C++20 编译)
然后我试了这个:
using Rep = int;
class my_duration
{
Rep rep_;
public:
my_duration() = default; // removed constexpr
};
int
main()
{
constexpr my_duration x{};
}
编译器再次喜欢它。
如果还没有关于此的 CWG 问题,可能应该有。行为似乎有点不一致。这可能只是因为我们(整个行业)仍在学习 Fixed in C++20.constexpr
.