说下面的Point类的默认构造函数是constexpr是否正确?

Fra*_*uet 3 c++ constexpr c++14

B. Stroustrup在他的书"TCPL"第4版的第265页上有以下例子:

struct Point{
    int x, y, z;
    constexpr Point up(int d) { return {x, y, z+d}; }
    constexpr Poind move(int dx, int dy) { return {x+dx, y+dy}; }
};
Run Code Online (Sandbox Code Playgroud)

后来他在第266页显示:

constexpr Point p1 {10, 20, 30};     // the default constructor is constexpr
Run Code Online (Sandbox Code Playgroud)

从N4140的§7.1.5/ 4开始,我发现了以下相关要点:

  • (4.4)其函数体应为= default,或其函数体的复合语句应满足constexpr函数的函数体的约束;
  • (4.5)应初始化每个非变量非静态数据成员和基类子对象(12.6.2);

关于上面的要点,我有两点意见:

  1. 说编译器生成的默认构造函数是否struct Point具有函数体是否正确= default
  2. 即使上面我的问题的答案是yes,我也在争论编译器为struct Pointis 生成默认构造函数的事实,constexpr因为这个构造函数没有初始化成员x,y并且z与上面的项目符号(4.5)相矛盾.我在这里纠正吗?

编辑我正在介绍第三个问题,我认为总结了我在这个问题上遇到的主要困难.

我无法生成constexpr其body等于的默认构造函数的示例= default.假设这是不可能的.显而易见的问题是:§7.1.5/ 4中的要点(4.4)的目的是什么?

Bar*_*rry 5

  1. 是.来自[class.ctor]:

如果没有用户声明的类X构造函数,则不会将没有参数的非显式构造函数隐式声明为defaultaulted(8.4).

隐式声明为默认的函数意味着它的功能就像它被显式声明为= default.

  1. 你是对的.默认构造函数不能用作constexpr,通过[dcl.init]进一步说明:

如果程序要求对const限定类型T的对象进行默认初始化,则T应为具有用户提供的默认构造函数的类类型.

所以以下是不正确的,因为没有用户提供的默认构造函数:

    constexpr Point p; // error
Run Code Online (Sandbox Code Playgroud)

我们在[dcl.constexpr]中也看到了这一点:

constexpr对象声明中使用的说明符将对象声明为const.这样的对象应具有文字类型并应初始化.如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式(5.20).否则,或者如果constexpr在引用声明中使用了说明符,则其初始值设定项中出现的每个全向表达式都应为常量表达式.[注意:用于转换初始化表达式和用于初始化的每个构造函数调用的每个隐式转换都是这种完整表达式的一部分.- 尾注]
[示例:

struct pixel {
    int x, y;
};
constexpr pixel ur = { 1294, 1024 };  // OK
constexpr pixel origin;               // error: initializer missing
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

由于默认构造函数没有为我们初始化(即使它没有使用户提供的要求失败),我们可以提供一个初始化程序来自己完成:

    constexpr Point q{}; // ok, all of q's members are 0
Run Code Online (Sandbox Code Playgroud)

这最终都与此无关:

constexpr Point p1 {10, 20, 30};     // the default constructor is constexpr
Run Code Online (Sandbox Code Playgroud)

根本不使用默认构造函数,并且实际执行聚合初始化,这满足上面引用的"应该初始化"子句.