2

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.

Unapiedra
  • 15,037
  • 12
  • 64
  • 93
  • Please suggest better tags. – Unapiedra Feb 15 '17 at 13:46
  • looks like [this](http://stackoverflow.com/questions/7411515/why-does-c-require-a-user-provided-default-constructor-to-default-construct-a) explains it. – NathanOliver Feb 15 '17 at 13:49
  • So newer versions of GCC and Clang are broken with regards to the standard? Surely, there must be a rule in the standard that allows the current behavior of these compilers. Your linked answer, while useful, did not answer this question to me. – Unapiedra Feb 15 '17 at 13:59
  • 1
    [This](http://stackoverflow.com/a/28338265/461597) might be the answer. It links to [this](http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#253) issue of the Standard Committee for C++11. Now, only a link to which resolution the Standard came is needed. – Unapiedra Feb 15 '17 at 14:03
  • You are correct, it's Core issue 253. GCC documented its change of behaviour for gcc 4.6 at https://gcc.gnu.org/gcc-4.6/changes.html#cplusplus – Jonathan Wakely Feb 15 '17 at 14:32

1 Answers1

4

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.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326