clang 与 gcc 中空结构的默认初始化程序

Default Initializer of empty struct in clang vs gcc

以下代码使用 GCC 的某些版本和 Clang 的某些版本编译(请参阅下面的版本)。

struct my_struct {};

int main(int argc, char** argv) {
  const my_struct my_object;
  return 0;
};

编译:g++ clang_error.cppclang++ clang_error.cpp。我在 4.8.4 有 g++,在 3.6.0.

有 clang++

错误信息是:

clang_error.cpp:7:19: error: default initialization of an object of const type 'const my_struct' without a user-provided default constructor
   const my_struct my_object;
                   ^
clang_error.cpp:7:28: note: add an explicit initializer to initialize 'my_object'
   const my_struct my_object;
                            ^
                             = {}
1 error generated.

受影响的版本

使用 Compiler Explorer here,我可以看到 GCC 高达 4.5.4 受到影响。 Clang 影响到 3.9.0。

问题

我的问题是:C++ 标准对此有何规定?理想情况下,我会关心 C++14,但我在那里并不挑剔。

上面的示例代码是否符合标准?

到目前为止我发现了什么

我在 C++14 的 Draft N3797 中找到了以下内容。

§ 7.1.6.1 The cv-qualifiers [dcl.type.cv]
2 [ Note: Declaring a variable const can affect its linkage (7.1.1) and its usability in constant expressions (5.19). As described in 8.5, the definition of an object or subobject of const-qualified type must specify an initializer or be subject to default-initialization. — end note ]

§ 8.5
7 To default-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9), the default constructor (12.1) for T is called (and the initialization is ill-formed if T has no default constructor or overload resolution (13.3) results in an ambiguity or in a function that is deleted or inaccessible from the context of the initialization);
— if T is an array type, each element is default-initialized;
— otherwise, no initialization is performed.

What does the C++ standard say about this?

Is the above example code standard-conformant?

在C++14中,是non-conformant:

n4431 (2015) standard draft [dcl.init] / 7:

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.

my_struct 没有 user-provided 默认构造函数,所以你不应该 default-initialize.

然而,一些较新的编译器似乎选择放宽规则,可能是因为它受到缺陷报告的影响:DR 253


即将出台的标准改变了措辞:

Current (2017) standard draft [dcl.init] / 7:

A class type T is const-default-constructible if default-initialization of T would invoke a user-provided constructor of T (not inherited from a base class) or if

(7.4) each direct non-variant non-static data member M of T has a default member initializer or, if M is of class type X (or array thereof), X is const-default-constructible,

(7.5) if T is a union with at least one non-static data member, exactly one variant member has a default member initializer,

(7.6) if T is not a union, for each anonymous union member with at least one non-static data member (if any), exactly one non-static data member has a default member initializer, and

(7.7) each potentially constructed base class of T is const-default-constructible.

If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.

这个措辞对我来说有点模棱两可,但我认为由于 my_struct 没有违反 7.4 的成员(并且不是联合,所以 7.5 不适用,没有联合成员所以 7.6 不适用不适用且没有基础,因此 7.7 不适用),它是 const-default-constructible 因此该示例将是一致的。