说下面 class Point 的默认构造函数是 constexpr 是否正确?
Is it correct to say that the default constructor for class Point below is constexpr?
乙。 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}; }
};
在第 266 页的后面,他显示:
constexpr Point p1 {10, 20, 30}; // the default constructor is constexpr
从 N4140 的 §7.1.5/4 中,我发现以下相关要点:
- (4.4) either its function-body shall be
= default
, or the compound-statement of its function-body shall satisfy the constraints
for a function-body of a constexpr function;
- (4.5) every non-variant non-static data member and base class sub-object shall be initialized (12.6.2);
关于上述要点,我有两个观察结果:
- 编译器为
struct Point
生成的默认构造函数具有函数体 = default
是否正确?
- 即使我上面的问题的答案是
yes
,我也在争论编译器为 struct Point
生成的默认构造函数是 constexpr
的事实,只是因为这个构造函数没有' 初始化成员 x
、y
和 z
,与上面的要点 (4.5) 相矛盾。我说得对吗?
编辑我要介绍第三个问题,我认为它总结了我在这个问题上的主要困难。
我无法生成主体等于 = default
的 constexpr
默认构造函数的示例。假设这是不可能的。显而易见的问题是:§7.1.5/4 中的要点 (4.4) 的目的是什么?
- 是的。来自 [class.ctor]:
If there is no user-declared constructor
for class X
, a non-explicit constructor having no parameters is implicitly declared as defaulted (8.4).
隐式声明为默认的函数意味着它的功能就好像它被显式声明为 = default
一样。
- 你是对的。默认构造函数不能用作
constexpr
,通过 [dcl.init]: 进一步明确
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type
with a user-provided default constructor.
因此以下格式错误,因为没有用户提供的默认构造函数:
constexpr Point p; // error
我们在 [dcl.constexpr] 中也看到了这一点:
A constexpr
specifier used in an object declaration declares the object as const
. Such an object shall have
literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.20). Otherwise, or if a constexpr
specifier is used in a reference declaration, every fullexpression
that appears in its initializer shall be a constant expression. [ Note: Each implicit conversion
used in converting the initializer expressions and each constructor call used for the initialization is part of
such a full-expression. —end note ]
[ Example:
struct pixel {
int x, y;
};
constexpr pixel ur = { 1294, 1024 }; // OK
constexpr pixel origin; // error: initializer missing
—end example ]
由于默认构造函数不会为我们初始化(即使它没有满足用户提供的要求),我们可以提供一个初始化器来自己完成:
constexpr Point q{}; // ok, all of q's members are 0
这一切最终都无关紧要,因为:
constexpr Point p1 {10, 20, 30}; // the default constructor is constexpr
根本不使用默认构造函数,实际上进行聚合初始化,满足上面引用的"shall be initialized"子句。
乙。 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}; }
};
在第 266 页的后面,他显示:
constexpr Point p1 {10, 20, 30}; // the default constructor is constexpr
从 N4140 的 §7.1.5/4 中,我发现以下相关要点:
- (4.4) either its function-body shall be
= default
, or the compound-statement of its function-body shall satisfy the constraints for a function-body of a constexpr function;- (4.5) every non-variant non-static data member and base class sub-object shall be initialized (12.6.2);
关于上述要点,我有两个观察结果:
- 编译器为
struct Point
生成的默认构造函数具有函数体= default
是否正确? - 即使我上面的问题的答案是
yes
,我也在争论编译器为struct Point
生成的默认构造函数是constexpr
的事实,只是因为这个构造函数没有' 初始化成员x
、y
和z
,与上面的要点 (4.5) 相矛盾。我说得对吗?
编辑我要介绍第三个问题,我认为它总结了我在这个问题上的主要困难。
我无法生成主体等于 = default
的 constexpr
默认构造函数的示例。假设这是不可能的。显而易见的问题是:§7.1.5/4 中的要点 (4.4) 的目的是什么?
- 是的。来自 [class.ctor]:
If there is no user-declared constructor for class
X
, a non-explicit constructor having no parameters is implicitly declared as defaulted (8.4).
隐式声明为默认的函数意味着它的功能就好像它被显式声明为 = default
一样。
- 你是对的。默认构造函数不能用作
constexpr
,通过 [dcl.init]: 进一步明确
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
因此以下格式错误,因为没有用户提供的默认构造函数:
constexpr Point p; // error
我们在 [dcl.constexpr] 中也看到了这一点:
A
constexpr
specifier used in an object declaration declares the object asconst
. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, that call shall be a constant expression (5.20). Otherwise, or if aconstexpr
specifier is used in a reference declaration, every fullexpression that appears in its initializer shall be a constant expression. [ Note: Each implicit conversion used in converting the initializer expressions and each constructor call used for the initialization is part of such a full-expression. —end note ]
[ Example:struct pixel { int x, y; }; constexpr pixel ur = { 1294, 1024 }; // OK constexpr pixel origin; // error: initializer missing
—end example ]
由于默认构造函数不会为我们初始化(即使它没有满足用户提供的要求),我们可以提供一个初始化器来自己完成:
constexpr Point q{}; // ok, all of q's members are 0
这一切最终都无关紧要,因为:
constexpr Point p1 {10, 20, 30}; // the default constructor is constexpr
根本不使用默认构造函数,实际上进行聚合初始化,满足上面引用的"shall be initialized"子句。