This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-11-11


2180. Virtual bases in destructors and defaulted assignment operators

Section: 11.4.6  [class.copy.assign]     Status: CD4     Submitter: Vinny Romano     Date: 2015-10-13

[Adopted at the February, 2016 meeting.]

According to 11.4.5.3 [class.copy.ctor] paragraph 28,

The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy/move assignment of its subobjects. The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, in the order in which they were declared in the class definition... It is unspecified whether subobjects representing virtual base classes are assigned more than once by the implicitly-defined copy/move assignment operator.

However, the determination of whether a defaulted copy/move assignment operator is defined as deleted (paragraph 23) considers only the “potentially constructed” subobjects:

A defaulted copy/move assignment operator for class X is defined as deleted if X has:

where “potentially constructed” is defined (in 11.4.4 [special] paragraph 5) as:

For a class, its non-static data members, 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.

i.e., excluding direct virtual base classes of abstract classes. This seems contradictory, since an implementation is expressly permitted to assign such base classes and thus presumably is permitted to fail if no such assignment is possible.

Similarly, 11.4.7 [class.dtor] paragraph 8 says,

After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X's direct non-variant non-static data members, the destructors for X's direct base classes and, if X is the type of the most derived class (11.9.3 [class.base.init]), its destructor calls the destructors for X's virtual base classes.

This appears to allow a virtual base's destructor to be called more than once, once for each class naming it as a direct virtual base and once for the most-derived class.

Proposed resolution (February, 2016):

  1. Change 11.4.7 [class.dtor] paragraph 8 as follows:

  2. After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X's direct non-variant non-static data members, the destructors for X's non-virtual direct base classes and, if X is the type of the most derived class (11.9.3 [class.base.init]), its destructor calls the destructors for X's virtual base classes. All destructors are called as if...
  3. Change 11.4.5.3 [class.copy.ctor] bullet 23.4 as follows:

  4. A defaulted copy/move assignment operator for class X is defined as deleted if X has: