7.1.5 的constexpr
说明符 [dcl.constexpr] 说:
的定义constexpr
构造函数应满足
以下要求:
- 该类不得有任何虚拟基类;
- 对于默认的复制/移动构造函数,该类不应具有作为变体成员的可变子对象;
- 每个参数类型应为文字类型;
- 其函数体不应是函数 try 块;
另外,它的函数体要么是=delete,要么是
满足以下要求:
- 其函数体应为 = default,或其函数体的复合语句应满足要求
对于 constexpr 函数的函数体;
- 应初始化每个非变体非静态数据成员和基类子对象(12.6.2);
- 如果该类是一个具有变体成员的联合体 (9.5),则应初始化其中的一个;
- 如果该类是类似联合的类,但不是联合,则对于其每个具有变体成员的匿名联合成员,恰好是以下之一
它们应被初始化;
- 对于非委托构造函数,选择初始化非静态数据成员和基类子对象的每个构造函数都应是
constexpr 构造函数;
- 对于委托构造函数,目标构造函数应是 constexpr 构造函数。
简而言之,= default
是 a 的有效定义constexpr
只要满足上述其他要求即可使用默认构造函数。
那么这是如何工作的未初始化的建筑?
事实并非如此。
例如:
constexpr seconds x1{};
以上工作并初始化x1
to 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;
^
为什么使此类成为非模板会破坏constexpr
默认构造函数?!
(Update:现在可以使用 C++20 进行编译)
然后我尝试了这个:
using Rep = int;
class my_duration
{
Rep rep_;
public:
my_duration() = default; // removed constexpr
};
int
main()
{
constexpr my_duration x{};
}
编译器再次喜欢它。
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
. Fixed in C++20.