gpt4 book ai didi

c++ - 没有初始值设定项或显式默认构造函数的空类是否可用作 constexpr 变量?

转载 作者:可可西里 更新时间:2023-11-01 16:38:40 25 4
gpt4 key购买 nike

给定以下代码:

struct f {
};

int main(){
constexpr f f1 ;
//const f f1 ; // This also has the same issue
//constexpr f f1 = {} ; //This works
}

clang 和 gcc 不同意它是否有效,clang 提供以下诊断 ( see it live ):

error: default initialization of an object of const type 'const f' without a user-provided default constructor
constexpr f f1 ;
^
{}

据我所知,f 是一种文字类型,它由隐式默认构造函数初始化,该构造函数应允许将其声明为 constexpr。谁是正确的?

请注意,如果我显式添加 constexpr 默认构造函数,clang 会接受 f1 的声明:

constexpr f() {} ;

答案是否改变为 f 不是聚合?

最佳答案

如果我们从 C++14 标准草案 7.1.5 [dcl.constexpr] 开始,我们可以发现对 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.19).

那么f是字面量类型吗?

3.9 部分 [basic.types] 说:

A type is a literal type if it is:

并涵盖以下项目符号中的类:

  • a class type (Clause 9) that has all of the following properties

    • it has a trivial destructor,
    • it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
    • all of its non-static data members and base classes are of non-volatile literal types.

所以我们对第一个和第三个项目符号没问题。为了覆盖第二个项目符号,我们可以注意到 f 是一个聚合,但是如果我们稍微修改一下示例,例如如果 f 看起来像这样:

struct f {
private:
int x = 0 ;
} ;

这在 C++11 或 C++14 中都不是聚合,但问题仍然存在。然后我们需要证明它有一个 constexpr 构造函数。 f 是否有 constexpr 构造函数?

据我所知,12.1 [class.ctor] 说是:

[...] If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr. [...]

但不幸的是,8.5 部分要求我们有一个用户提供的构造函数,它说:

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.

所以看起来 clang 在这里是正确的,如果我们查看以下 clang 错误报告:"error: default initialization of an object of const type 'const Z' requires a user-provided default constructor" even when no constructor needed .因此,由于 defect report 253,clang 是基于他们对此缺乏支持。目前没有建议的措辞,它说(强调我的):

Paragraph 9 of 8.5 [dcl.init] says:

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for an object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.

如果 const POD 对象没有非静态数据成员怎么办?对于这种情况,这种措辞需要一个空的初始值设定项

[...]

类似的注释适用于非 POD const 对象,其所有非静态数据成员和基类子对象都具有默认构造函数。为什么要求此类对象的类具有用户声明的默认构造函数?

缺陷报告仍处于打开状态,但对其的最后评论是:

If the implicit default constructor initializes all subobjects, no initializer should be required.

还有注释:

This issue should be brought up again in light of constexpr constructors and non-static data member initializers.

请注意,自缺陷报告出现以来,8.5 部分中对 const 限定类型的约束有所改变。这是由于提议 N2762: Not so Trivial Issues with Trivial这是 C++11 之前的版本。

虽然缺陷报告仍然开放,但考虑到 constexpr 更改和非静态数据成员初始化器,它似乎不再是必要的限制。特别是考虑以下对 constexpr 构造函数的要求:

  • every non-variant non-static data member and base class sub-object shall be initialized (12.6.2);

关于c++ - 没有初始值设定项或显式默认构造函数的空类是否可用作 constexpr 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33813929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com