Title
constexpr defaulted default constructors
Status
cd6
Section
11.4.5 [class.ctor]
Submitter
Richard Smith

Created on 2011-08-16.00:00:00 last changed 14 months ago

Messages

Date: 2014-05-27.00:00:00

Additional notes, May, 2014:

The proposed resolution inadvertently allows a defaulted default constructor of a class with virtual bases to be constexpr. It has been updated with a change addressing that oversight and returned to "review" status.

See also issue 1890.

Date: 2014-05-15.00:00:00

Proposed resolution (May, 2014):

Change 11.4.5 [class.ctor] paragraphs 4-5 as follows:

A defaulted default constructor for class X is defined as deleted if:

  • ...

  • any potentially constructed subobject has a type with a destructor that is deleted or inaccessible from the defaulted default constructor.

An implicitly-declared default constructor is constexpr if:

  • X has no virtual bases; and

  • for each non-variant non-static data member or base class subobject M, either M is initialized via brace-or-equal-initializer or default-initialization of M uses a constexpr constructor; and

  • if X is a union having variant members, or, if X is a non-union-class, for each anonymous union member having variant members, exactly one non-static data member is initialized via brace-or-equal-initializer.

A default constructor is trivial if it is not user-provided and if:

  • ...

  • for all the non-static data members of its class that are of class type (or array thereof), each such class has a trivial default constructor.

Otherwise, the default constructor is non-trivial.

A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (6.3 [basic.def.odr]) to create an object of its class type (6.7.2 [intro.object]) or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (11.9.3 [class.base.init]) and an empty compound-statement. If that user-written default constructor would be ill-formed, the program is ill-formed. If that user-written default constructor would satisfy the requirements of a constexpr constructor (9.2.6 [dcl.constexpr]), the implicitly-defined default constructor is constexpr. Before the defaulted default constructor for a class is implicitly defined, all the non-user-provided default constructors for its base classes and its non-static data members shall have been implicitly defined. [Note:...

Date: 2013-09-15.00:00:00

Notes from the September, 2013 meeting:

This issue should be resolved together with issue 1397.

Date: 2013-02-15.00:00:00

Additional notes (February, 2013):

As an example of this issue, consider:

  struct S {
    int i = sizeof(S);
  };

You can't determine the value of the initializer, and thus whether the initializer is a constant expression, until the class is complete, but you can't complete the class without declaring the default constructor, and whether that constructor is constexpr or not depends on whether the member initializer is a constant expression.

A similar issue arises with the following example:

  struct A {
    int x = 37;
    struct B { int x = 37; } b;
    B b2[2][3] = { { } };
  };

This introduces an order dependency that is not specified in the current text: determining whether the default constructor of A is constexpr requires first determining the characteristics of the initializer of B::x and whether B::B() is constexpr or not.

The problem is exacerbated with class templates, since the current direction of CWG is to instantiate member initializers only when they are needed (see issue 1396). For a specific example:

  struct S;
  template<class T> struct X {
    int i = T().i;
  };
  unsigned n = sizeof(X<S>); // Error?
  struct S { int i; };

This also affects determining whether a class template specialization is a literal type or not; presumably getting the right answer to that requires instantiating the class and all its nonstatic data member initializers.

See also issues 1397 and 1594.

Date: 2023-02-07.18:56:51

[ Resolved by P2448R2, applied in July 2022. ]

According to 11.4.5 [class.ctor] paragraph 6, a defaulted default constructor is constexpr if the corresponding user-written constructor would satisfy the constexpr requirements. However, the requirements apply to the definition of a constructor, and a defaulted constructor is defined only if it is odr-used, leaving it indeterminate at declaration time whether the defaulted constructor is constexpr or not.

(See also issue 1358.)

History
Date User Action Args
2023-02-07 18:56:51adminsetstatus: review -> cd6
2023-02-07 14:43:26adminsetstatus: review -> review
2023-02-06 00:00:00adminsetstatus: cd6 -> review
2023-01-29 22:11:52adminsetstatus: drafting -> cd6
2014-05-27 00:00:00adminsetmessages: + msg4995
2014-03-03 00:00:00adminsetmessages: + msg4890
2013-10-14 00:00:00adminsetmessages: + msg4629
2013-03-18 00:00:00adminsetmessages: + msg4258
2011-08-16 00:00:00admincreate