Title
Unions should not require a non-static data member of literal type
Status
c++23
Section
6.8.1 [basic.types.general]
Submitter
Richard Smith

Created on 2022-06-18.00:00:00 last changed 16 months ago

Messages

Date: 2022-11-20.07:54:16

Proposed resolution (approved by CWG 2022-11-09):

Change 6.8.1 [basic.types.general] paragraph 10 as follows:

A type is a literal type if it is:

  • ...

  • a possibly cv-qualified class type (Clause 11 [class]) that has all of the following properties:

    • it has a constexpr destructor (9.2.6 [dcl.constexpr]),

    • all of its non-static non-variant data members and base classes are of non-volatile literal types, and

    • it is either

      • is a closure type (7.5.6.2 [expr.prim.lambda.closure]),

      • an aggregate type (9.4.2 [dcl.init.aggr]),

      • is an aggregate union type that has either no variant members or at least one variant member of non-volatile literal type,

      • is a non-union aggregate type for which each of its anonymous union members satisfies the above requirements for an aggregate union type, or

      • has at least one constexpr constructor or constructor template (possibly inherited (9.9 [namespace.udecl]) from a base class) that is not a copy or move constructor,.

    • if it is a union, at least one of its non-static data members is of non-volatile literal type, and

    • if it is not a union, all of its non-static data members and base classes are of non-volatile literal types.

Date: 2022-11-09.23:17:18

Proposed resolution (CWG telecon 2022-08-12) [SUPERSEDED]:

Change in 6.8.1 [basic.types.general] paragraph 10 as follows:

A type is a literal type if it is:
  • ...
  • a possibly cv-qualified class type (Clause 11 [class]) that has all of the following properties:
    • it has a constexpr destructor (9.2.6 [dcl.constexpr]),
    • all of its non-static non-variant data members and base classes are of non-volatile literal types, and
    • it is either
      • is a closure type (7.5.6.2 [expr.prim.lambda.closure]),
      • is an aggregate type (9.4.2 [dcl.init.aggr]) for which that type (if it is a union) or each of its anonymous union members (otherwise) either has at least one variant member of non-volatile literal type or has no variant members, or
      • has at least one constexpr constructor or constructor template (possibly inherited (9.9 [namespace.udecl]) from a base class) that is not a copy or move constructor, .
    • if it is a union, at least one of its non-static data members is of non-volatile literal type, and
    • if it is not a union, all of its non-static data members and base classes are of non-volatile literal types.
Date: 2022-11-09.23:17:18

Suggested resolution [SUPERSEDED]:

Change in 6.8.1 [basic.types.general] paragraph 10 as follows:

A type is a literal type if it is:
  • ...
  • a possibly cv-qualified class type (Clause 11 [class]) that has all of the following properties:
    • it has a constexpr destructor (9.2.6 [dcl.constexpr]),
    • it is either
      • is a closure type (7.5.6.2 [expr.prim.lambda.closure]),
      • is an aggregate type (9.4.2 [dcl.init.aggr]) for which that type (if it is a union) or each of its anonymous union members (otherwise) either has at least one variant member of non-volatile literal type or has no variant members, or
      • has at least one constexpr constructor or constructor template (possibly inherited (9.9 [namespace.udecl]) from a base class) that is not a copy or move constructor, and
    • if it is a union, at least one of its non-static data members is of non-volatile literal type, and
    • if it is not a union, all of its non-static non-variant data members and base classes are of non-volatile literal types.
Date: 2022-11-15.00:00:00

[Accepted as a DR at the November, 2022 meeting.]

According to 6.8.1 [basic.types.general] paragraph 10, a type is a literal type only if it satisfies the following:

A type is a literal type if it is:
  • ...
  • a possibly cv-qualified class type (Clause 11 [class]) that has all of the following properties:
    • it has a constexpr destructor (9.2.6 [dcl.constexpr]),
    • it is either a closure type (7.5.6.2 [expr.prim.lambda.closure]), an aggregate type (9.4.2 [dcl.init.aggr]), or has at least one constexpr constructor or constructor template (possibly inherited (9.9 [namespace.udecl]) from a base class) that is not a copy or move constructor,
    • if it is a union, at least one of its non-static data members is of non-volatile literal type, and
    • if it is not a union, all of its non-static data members and base classes are of non-volatile literal types.
[Note 4: A literal type is one for which it might be possible to create an object within a constant expression. ... —end note]

However, the normative rule disagrees with the note. Consider:

  struct A { A(); };
  union U {
    A a;
    constexpr U() {}
    constexpr ~U() {}
  };

It is certainly possible to create an object of type U in a constant expression, even though U is not a literal type.

In the suggested resolution, the aggregate type rule is intended to capture the fact that it is not possible for aggregate initialization of a non-empty union to leave no active member (and similarly for each anonymous union member in a non-union union-like class).

History
Date User Action Args
2023-07-16 13:00:43adminsetstatus: open -> c++23
2023-07-16 13:00:43adminsetstatus: drwp -> open
2023-02-18 18:43:04adminsetstatus: dr -> drwp
2022-11-25 05:14:04adminsetstatus: ready -> dr
2022-11-09 23:17:18adminsetmessages: + msg6991
2022-11-09 21:39:20adminsetstatus: tentatively ready -> ready
2022-08-19 07:54:33adminsetmessages: + msg6890
2022-08-19 07:54:33adminsetstatus: open -> tentatively ready
2022-06-21 06:32:55adminsetmessages: + msg6857
2022-06-18 00:00:00admincreate