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

2024-03-20


1282. Underspecified destructor exception-specification

Section: 14.5  [except.spec]     Status: CD3     Submitter: Daniel Krügler     Date: 2011-03-28

[Voted into the WP at the February, 2012 meeting; moved to DR at the October, 2012 meeting.]

It is not clear whether the unexpected handler will be invoked in the following example:

  #include <iostream>
  #include <exception>

  struct A { ~A() throw() { } };
  struct B { ~B() noexcept { } };
  struct C : A, B { ~C() { throw 0; } };

  void unexpected_observer() {
   std::cerr << "unexpected called" << std::endl;
   std::terminate();
  }

  int main() {
   std::set_unexpected(unexpected_observer);
   C c;
  }

The problem is 14.5 [except.spec] paragraph 14 only says that the exception-specification of C::~C “shall allow no exceptions,” which could mean either throw() or noexcept(true).

Proposed resolution (August, 2011):

Change 14.5 [except.spec] paragraph 14 as follows:

An implicitly declared special member function (11.4.4 [special]) shall have has an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f's implicit definition; f shall allow allows all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions has the exception-specification noexcept(true) if every function it directly invokes allows no exceptions. [Example:

  struct A {
    A();
    A(const A&) throw();
    A(A&&) throw();
    ~A() throw(X);
  };
  struct B {
    B() throw();
    B(const B&) throw();
    B(B&&) throw(Y);
    ~B() throw(Y);
  };
  struct D : public A, public B {
      // Implicit declaration of D::D();
      // Implicit declaration of D::D(const D&) throw() noexcept(true);
      // Implicit declaration of D::D(D&&) throw(Y);
      // Implicit declaration of D::~D() throw(X, Y);
  };

Furthermore, if...