Title
Implicitly deleted destructors for union-like classes
Status
open
Section
11.4.7 [class.dtor]
Submitter
Jakub Jelinek

Created on 2026-05-04.00:00:00 last changed 5 days ago

Messages

Date: 2026-05-10.05:55:39

Suggested resolution:

  1. Change in 11.4.4 [special] paragraph 7 as follows:

    For a class, its direct non-static data members, excluding anonymous union members (but including variant members thereof), its non-virtual direct base classes, and, if the class is not abstract (11.7.4 [class.abstract]), its virtual base classes are called its potentially constructed subobjects.
  2. Change in 11.4.7 [class.dtor] paragraph 4 as follows:

    A defaulted destructor for a class X is defined as deleted if
    • X is has a non-union class and any non-variant potentially constructed subobject has S of class type M (or possibly multidimensional array thereof) where either
      • S is not a variant member and M has a destructor that is deleted or is inaccessible from the defaulted destructor, or
    • X is a union and
      • overload resolution to select a constructor to default-initialize an object of type X either fails or selects a constructor that is either deleted or not trivial, or
      • X has a variant member V of class type M (or possibly multi-dimensional array thereof) where
      • S is a variant member, M has a destructor that is deleted, inaccessible from the defaulted destructor, or non-trivial, and either
        • V S has a default member initializer or
        • X has a user-provided constructor,
        and M has a destructor that is non-trivial, or,
    • for a virtual destructor, lookup of the non-array deallocation function results in an ambiguity or in a function that is deleted or inaccessible from the defaulted destructor.
  3. Change in 11.9.3 [class.base.init] bullet 9.2 as follows:

    In a non-delegating constructor other than an implicitly-defined copy/move constructor (11.4.5.3 [class.copy.ctor]), if a given potentially constructed subobject is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then
    • if the entity is a non-static data member that has a default member initializer (11.4 [class.mem]) and either
      • the constructor's class is a union (11.5 [class.union]), and no other variant member of that union is designated by a mem-initializer-id or
      • the constructor's class is not a union, and, if the entity is a member of an anonymous union, no other member of that union is designated by a mem-initializer-id,
      the entity is initialized from its default member initializer as specified in 9.5 [dcl.init];
    • otherwise, if the entity is an anonymous union or a variant member (11.5.2 [class.union.anon]), no initialization is performed;
    • otherwise, the entity is default-initialized (9.5 [dcl.init]).
Date: 2026-05-04.00:00:00

Consider:

  union U1 {
    int a = 42;
    long b;
  } u1;

  union U2 {
    U2(int i): i(i) { }
    int i;
  } u2(5);

Both declarations ought to be well-formed, but the current rules (as amended by paper P3726R2) make both ill-formed.

History
Date User Action Args
2026-05-07 20:57:17adminsetmessages: + msg8569
2026-05-04 00:00:00admincreate