空类是否可用作没有初始化程序或显式默认构造函数的constexpr变量? [英] Is an empty class usable as a constexpr variable without an initializer or explicit default constructor?

查看:224
本文介绍了空类是否可用作没有初始化程序或显式默认构造函数的constexpr变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下代码:

struct f {
};

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

clang和gcc在是否有效上存在分歧,clang提供了以下诊断信息( 请参见直播 ):

clang and gcc disagree over whether it is valid, with clang providing the following diagnostic (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.谁是对的?

As far as I can tell f is a literal type and it is initialized by the implicitly defaulted constructor which should allow it to be declared constexpr. Who is correct here?

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

Note, clang does accept the declaration of f1 if I explicitly add a constexpr default constructor:

constexpr f() {} ;

答案是否更改为f不是汇总?

Does the answer change is f is not an aggregate?

推荐答案

如果我们从C ++ 14标准草案草案7.1.5 [dcl.constexpr] 开始,我们可以找到以下要求: constexpr对象声明为:

If we start from the draft C++14 standard section 7.1.5 [dcl.constexpr] we can find the requirements for a constexpr object declaration are:

在对象声明中使用的constexpr说明符将该对象声明为const.此类物体应具有 文字类型,应进行初始化.如果它是通过构造函数调用初始化的,则该调用应为常量表达式(5.19).

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 [基本类型] 说:

如果是,则类型为文字类型

A type is a literal type if it is:

并在以下项目符号中介绍了这些类:

and covers classes in the following bullet:

  • 具有以下所有属性的类类型(第9条)

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

  • 它有一个琐碎的析构函数,
  • 它是聚合类型(8.5.1)或具有至少一个constexpr构造函数或构造函数模板 不是复制或移动构造函数,并且
  • 其所有非静态数据成员和基类均为非易失性文字类型.
  • 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 aggregate ,但是如果我们稍微修改示例,例如f看起来像这样:

So we are okay on the first and third bullet. To cover the second bullet, we could note that f is an aggregate but if we modify the example slightly, for example if f looked like this:

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

在C ++ 11或C ++ 14中都不是合计的,但问题仍然存在.然后,我们需要显示它具有constexpr构造函数. f是否具有constexpr构造函数?

which would not be an aggregate in either C++11 or C++14 but the issue would still exist. Then we need to show it has a constexpr constructor. Does f have a constexpr constructor?

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

[...]如果该用户编写的默认构造函数将满足constexpr构造函数(7.1.5)的要求, 隐式定义的默认构造函数为constexpr. [...]

[...] 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部分中要求用户提供构造函数,

But we are unfortunately required to have a user-provided constructor by section 8.5 which says:

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

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似乎是正确的:错误:const类型'const Z'的对象的默认初始化需要用户提供的默认构造函数",即使不需要构造函数也是如此.因此,由于报告253 ,目前尚无建议的措词,并说(强调我的):

So it looks like clang is correct here and if we look at the following clang bug report: "error: default initialization of an object of const type 'const Z' requires a user-provided default constructor" even when no constructor needed. So clang is basing their lack of support for this due to defect report 253 which does not currently have a proposed wording and it says (emphasis mine):

8.5 [dcl.init]第9段说:

Paragraph 9 of 8.5 [dcl.init] says:

如果未为对象指定初始化程序,并且该对象属于 (可能具有CV资格)非POD类类型(或其数组), 对象应被默认初始化; 如果对象是 const限定类型,基础类类型应具有 用户声明的默认构造函数.否则,如果没有初始化程序,则为 为对象指定的,该对象及其子对象(如果有)具有 不确定的初始值;如果对象或其任何子对象 属于const限定类型,程序格式错误.

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对象没有非静态数据成员该怎么办?在这种情况下,这种措词需要一个空的初始化程序

What if a const POD object has no non-static data members? This wording requires an empty initializer for such cases

[...]

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

Similar comments apply to a non-POD const object, all of whose non-static data members and base class subobjects have default constructors. Why should the class of such an object be required to have a user-declared default constructor?

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

The defect report is still open but the last comment on it says:

如果隐式默认构造函数初始化所有子对象,则不需要初始化程序.

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

并注意:

应该根据constexpr构造函数和非静态数据成员初始化程序再次提出此问题.

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

请注意,自缺陷报告发布以来,在8.5节中四处移动的const限定类型的约束.这是由于提案 N2762:并非如此琐碎的问题是在C ++ 11之前的Trivial 中实现的.

Note the constraints on const qualified types moved around in section 8.5 since the defect report came about. This was due to proposal N2762: Not so Trivial Issues with Trivial which was pre C++11.

尽管缺陷报告仍处于打开状态,但鉴于constexpr更改和非静态数据成员初始化程序,它似乎不再是必要的限制.尤其要考虑对constexpr构造函数的以下要求:

Although the defect report is still open, given the constexpr changes and non-static data member initializers it does not seem like a necessary restriction anymore. Especially considering the following requirement on a constexpr constructor:

  • 每个不变的非静态数据成员和基类子对象都应初始化(12.6.2);
  • every non-variant non-static data member and base class sub-object shall be initialized (12.6.2);

这篇关于空类是否可用作没有初始化程序或显式默认构造函数的constexpr变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆