Unapiedra
Unapiedra

Reputation: 16197

Default Initializer of empty struct in clang vs gcc

The following code compiles with some versions with GCC and some versions of Clang (see below which versions).

struct my_struct {};

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

Compile with :g++ clang_error.cpp and clang++ clang_error.cpp. Where I had g++ at 4.8.4 and clang++ at 3.6.0.

The error message is:

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.

Versions affected

Using the Compiler Explorer here, I can see that GCC up to 4.5.4 is affected. Clang is affected up to 3.9.0.

Question

My question is: What does the C++ standard say about this? Ideally, I'd care about C++14 but I'm not picky there.

Is the above example code standard-conformant?

What I found so far

I found the following in Draft N3797 of C++14.

§ 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.

Upvotes: 2

Views: 932

Answers (1)

eerorika
eerorika

Reputation: 238311

What does the C++ standard say about this?

Is the above example code standard-conformant?

In C++14, it is 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 has no user-provided default constructor, so you shall not default-initialize.

However, some newer compilers appear to have chosen to relax the rule, possibly because it is subject to a defect report: DR 253.


The upcoming standard has changed wording:

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.

The wording is a bit ambiguous to me, but I think that since my_struct has no members that violate 7.4 (and is not a union, so 7.5 does not apply, has no union members so 7.6 does not apply and no bases, so 7.7 does not apply), it is const-default-constructible and therefore the example will be conformant.

Upvotes: 4

Related Questions