Home > Back-end >  constructor is implicitly deleted because its exception-specification does not match the implicit ex
constructor is implicitly deleted because its exception-specification does not match the implicit ex

Time:01-05

Can anyone explain me why using constructor marked as default will have the error but the other one doesn't have. My understanding is they are very much similar. Thanks.

class B {
public:
    B() {
        throw int(42);
    }
};

class A {
public:
    A() noexcept = default; // error: use of deleted function ‘A::A()’
                            // note: ‘A::A() noexcept’ is implicitly deleted because
                            // its exception-specification does not match the implicit exception-specification ‘’
    //A() noexcept : m_b{}{}
    B m_b;
};

CodePudding user response:

Implicit default constructor exception specification differs from your declaration of explicit default constructor. Here's the relevant (although outdated) part of the standard:

If a function that is explicitly defaulted is declared with an exception-specification that is not compatible (15.4) with the exception specification on the implicit declaration, then

  • if the function is explicitly defaulted on its first declaration, it is defined as deleted;
  • otherwise, the program is ill-formed.

In 2019 the proposal was made to change this behaviour. As I understand in c 20 your code will run just fine.

CodePudding user response:

Originally, the declaration of the constructor was already ill-formed, the idea being that the defaulted function ought to behave identically to the implicit declaration. Your explicit implementation has no such restriction: noexcept functions are allowed to call potentially throwing functions, and the behavior is even well-defined if they throw.

In C 14 it was relaxed to be merely deleted in that case. Later it was realized that even that was too restrictive (and difficult to implement correctly), so it was relaxed again: now the exception specification can be anything (but there’s still an automatic one for defaulted functions).

Both of these changes were retroactive, so you’ll see a dependence on compiler version more than language version.

Note that none of this depends on the actual throw in B::B: that constructor is potentially throwing regardless.

  •  Tags:  
  • c
  • Related