[except.spec] (original) (raw)

14 Exception handling [except]

14.5 Exception specifications [except.spec]

The predicate indicating whether a function cannot exit via an exception is called the exception specification of the function.

If the predicate is false, the function has apotentially-throwing exception specification, otherwise it has anon-throwing exception specification.

The exception specification is either defined implicitly, or defined explicitly by using a noexcept-specifieras a suffix of a function declarator.

In a noexcept-specifier, the constant-expression, if supplied, shall be a contextually converted constant expression of type bool ([expr.const]); that constant expression is the exception specification of the function type in which the noexcept-specifier appears.

A ( token that follows noexcept is part of thenoexcept-specifier and does not commence an initializer ([dcl.init]).

[Example 1: void f() noexcept(sizeof(char[2])); void g() noexcept(sizeof(char)); — _end example_]

If a declaration of a function does not have a noexcept-specifier, the declaration has a potentially throwing exception specification unless it is a destructor or a deallocation function or is defaulted on its first declaration, in which cases the exception specification is as specified below and no other declaration for that function shall have a noexcept-specifier.

If a noexcept-specifier is specified in an explicit instantiation, the exception specification shall be the same as the exception specification of all other declarations of that function.

A diagnostic is required only if the exception specifications are not the same within a single translation unit.

If a virtual function has a non-throwing exception specification, all declarations, including the definition, of any function that overrides that virtual function in any derived class shall have a non-throwing exception specification, unless the overriding function is defined as deleted.

[Example 2: struct B { virtual void f() noexcept;virtual void g();virtual void h() noexcept = delete;};struct D: B { void f(); void g() noexcept; void h() = delete; };

The declaration ofD​::​fis ill-formed because it has a potentially-throwing exception specification, whereasB​::​fhas a non-throwing exception specification.

— _end example_]

An expression E ispotentially-throwing if

An implicitly-declared constructor for a class X, or a constructor without a noexcept-specifierthat is defaulted on its first declaration, has a potentially-throwing exception specification if and only if any of the following constructs is potentially-throwing:

[Note 1:

Even though destructors for fully-constructed subobjects are invoked when an exception is thrown during the execution of a constructor ([except.ctor]), their exception specifications do not contribute to the exception specification of the constructor, because an exception thrown from such a destructor would call the function std​::​terminaterather than escape the constructor ([except.throw], [except.terminate]).

— _end note_]

The exception specification for an implicitly-declared destructor, or a destructor without a noexcept-specifier, is potentially-throwing if and only if any of the destructors for any of its potentially constructed subobjects has a potentially-throwing exception specification or the destructor is virtual and the destructor of any virtual base class has a potentially-throwing exception specification.

The exception specification for an implicitly-declared assignment operator, or an assignment-operator without a noexcept-specifierthat is defaulted on its first declaration, is potentially-throwing if and only if the invocation of any assignment operator in the implicit definition is potentially-throwing.

The exception specification for a comparison operator function ([over.binary]) without a noexcept-specifierthat is defaulted on its first declaration is potentially-throwing if and only if any expression in the implicit definition is potentially-throwing.

[Example 3: struct A { A(int = (A(5), 0)) noexcept; A(const A&) noexcept; A(A&&) noexcept;~A();};struct B { B() noexcept; B(const B&) = default; B(B&&, int = (throw 42, 0)) noexcept;~B() noexcept(false);};int n = 7;struct D : public A, public B { int * p = new int[n];};

Furthermore, ifA​::​~A()were virtual, the program would be ill-formed since a function that overrides a virtual function from a base class shall not have a potentially-throwing exception specification if the base class function has a non-throwing exception specification.

— _end example_]

An exception specification is considered to be needed when:

The exception specification of a defaulted function is evaluated as described above only when needed; similarly, thenoexcept-specifier of a specialization of a templated function is instantiated only when needed.