Title
Deleted default constructor for abstract class via destructor
Status
c++14
Section
11.4.5 [class.ctor]
Submitter
Richard Smith

Created on 2013-08-26.00:00:00 last changed 121 months ago

Messages

Date: 2014-02-15.00:00:00

[Moved to DR at the February, 2014 meeting.]

Date: 2013-11-15.00:00:00

Proposed resolution (November, 2013):

  1. Add the following as a new paragraph at the end of 11.4.4 [special]:

  2. 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.
  3. Change 11.4.5 [class.ctor] paragraph 4 as follows:

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

    • ...

    • any direct or virtual base class, or non-static data member potentially constructed subobject, except for a non-static data member with no a brace-or-equal-initializer, has class type M (or array thereof) and either M has no default constructor or overload resolution (12.2 [over.match]) as applied to M's default constructor results in an ambiguity or in a function that is deleted or inaccessible from the defaulted default constructor, or

    • any direct or virtual base class or non-static data member potentially constructed subobject has a type with a destructor that is deleted or inaccessible from the defaulted default constructor.

  5. Change 11.4.7 [class.dtor] paragraph 5 as follows:

  6. A defaulted destructor for a class X is defined as deleted if:

    • X is a union-like class that has a variant member with a non-trivial destructor,

    • any of the non-static data members potentially constructed subobject has class type M (or array thereof) and M has a deleted destructor or a destructor that is inaccessible from the defaulted destructor,

    • any direct or virtual base class has a deleted destructor or a destructor that is inaccessible from the defaulted destructor,

  7. Change 11.9.3 [class.base.init] paragraph 8 as follows:

  8. In a non-delegating constructor, if a given non-static data member or base class 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) and the entity is not a virtual base class of an abstract class (11.7.4 [class.abstract]), then...
  9. Change 11.9.3 [class.base.init] paragraph 10 as follows:

  10. In a non-delegating constructor, the destructor for each direct or virtual base class and for each non-static data member potentially constructed subobject of class type is potentially invoked (11.4.7 [class.dtor]). [Note: This provision ensures that destructors can be called for fully-constructed sub-objects in case an exception is thrown (14.3 [except.ctor]). —end note]
  11. Change 11.4.5.3 [class.copy.ctor] paragraph 8, replacing the bulleted list with a single sentence, as follows:

  12. The implicitly-declared copy constructor for a class X will have the form

      X::X(const X&)

    if each potentially constructed subobject

    • each direct or virtual base class B of X has a copy constructor whose first parameter is of type const B& or const volatile B&, and

    • for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy constructor whose first parameter is of type const M& or const volatile M&.121

    Otherwise...

  13. Change 11.4.5.3 [class.copy.ctor] paragraph 11 as follows:

  14. An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (9.5.3 [dcl.fct.def.delete]) if X has:

    • a variant member with a non-trivial corresponding constructor and X is a union-like class,

    • a non-static data member potentially constructed subobject of class type M (or array thereof) that cannot be copied/moved because overload resolution (12.2 [over.match]), as applied to M's corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,

    • a direct or virtual base class B that cannot be copied/moved because overload resolution (12.2 [over.match]), as applied to B's corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,

    • any direct or virtual base class or non-static data member potentially constructed subobject of a type with a destructor that is deleted or inaccessible from the defaulted constructor, or,

    • ...

  15. Change 11.4.5.3 [class.copy.ctor] paragraph 14 as follows:

  16. Before the defaulted copy/move constructor for a class is implicitly defined, all non-user-provided copy/move constructors for its direct and virtual base classes and its non-static data members potentially constructed subobjects shall have been implicitly defined. [Note: An implicitly-declared copy/move constructor has an exception-specification (14.5 [except.spec]). —end note]
  17. Change 11.4.5.3 [class.copy.ctor] paragraph 23 as follows:

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

    • ...

    • a non-static data member potentially constructed subobject of class type M (or array thereof) that cannot be copied/moved because overload resolution (12.2 [over.match]), as applied to M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator, or.

    • a direct or virtual base class B that cannot be copied/moved because overload resolution (12.2 [over.match]), as applied to B's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.

This resolution also resolves issue 1611.

Date: 2022-09-25.18:08:42

While reviewing the resolution of issue 1611, it was noticed that the final bullet of 11.4.5 [class.ctor] paragraph 4 has a similar issue:

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

  • ...

  • any direct or virtual base class or non-static data member has a type with a destructor that is deleted or inaccessible from the defaulted default constructor.

Presumably destructors for virtual bases of abstract classes should not be considered in making this determination.

A question was also raised regarding whether odr-use is correctly defined for destructors of virtual bases of abstract classes. 6.3 [basic.def.odr] paragraph 3 simply refers to 11.4.7 [class.dtor], where the relevant passage (paragraph 8) reads,

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.

It could be argued, particularly in light of the reference to 11.9.3 [class.base.init], that this is clear enough that the destructor for an abstract class does not invoke destructors for its virtual bases, but a note to that effect might be helpful.

History
Date User Action Args
2014-11-24 00:00:00adminsetstatus: dr -> c++14
2014-03-03 00:00:00adminsetmessages: + msg4957
2014-03-03 00:00:00adminsetstatus: tentatively ready -> dr
2014-01-20 00:00:00adminsetmessages: + msg4735
2014-01-20 00:00:00adminsetstatus: drafting -> tentatively ready
2013-10-14 00:00:00adminsetstatus: open -> drafting
2013-08-26 00:00:00admincreate