This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 112c. See for the official list.


2426. Reference to destructor that cannot be invoked

Section: 14.3  [except.ctor]     Status: C++20     Submitter: Mike Miller     Date: 2019-08-13

[Adopted as a DR at the November, 2019 meeting.]

Consider the following example:

   template<typename T> struct A {
     ~A() {}
   A<char> g();
   A<char> f() { return g(); }

According to 14.3 [except.ctor] paragraph 2,

If an exception is thrown during the destruction of temporaries or local variables for a return statement (8.7.4 [stmt.return]), the destructor for the returned object (if any) is also invoked.

In f() there is no possibility of an exception occuring during the processing of the return statement, so there appears to be no reason for a reference to the private destructor of A<char>. Current implementations, however, issue an access error for this example. Is wording needed to make that destructor potentially invoked in such cases?

Proposed resolution (September, 2019):

  1. Change 8.7.4 [stmt.return] paragraph 2 as follows:

  2. ...[Note: A return statement can involve an invocation of a constructor to perform a copy or move of the operand if it is not a prvalue or if its type differs from the return type of the function. A copy operation associated with a return statement may be elided or converted to a move operation if an automatic storage duration variable is returned (11.9.6 [class.copy.elision]). —end note] [Example:

      std::pair<std::string,int> f(const char* p, int x) {
        return {p,x};
    end example] The destructor for the returned object is potentially invoked (11.4.7 [class.dtor], 14.3 [except.ctor]). [Example:
      class A {
        ~A() {}
      A f() { return A(); }   // error: destructor of A is private (even though it is never invoked)
    end example] Flowing off the end...
  3. Change 11.4.7 [class.dtor] paragraph 14 as follows:

  4. A destructor can also be invoked explicitly. A destructor is potentially invoked if it is invoked or as specified in [], 8.7.4 [stmt.return], 9.4.2 [dcl.init.aggr], 11.9.3 [class.base.init], and 14.2 [except.throw]. A program is ill-formed if a destructor that is potentially invoked is deleted or not accessible from the context of the invocation.