[except.spec] # 14 Exception handling [[except]](./#except) ## 14.5 Exception specifications [except.spec] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L752) The predicate indicating whether a function cannot exit via an exception is called the [*exception specification*](#def:exception_specification "14.5 Exception specifications [except.spec]") of the function[.](#1.sentence-1) If the predicate is false, the function has a[*potentially-throwing exception specification*](#def:potentially-throwing,exception_specification "14.5 Exception specifications [except.spec]"), otherwise it has a[*non-throwing exception specification*](#def:non-throwing_exception_specification "14.5 Exception specifications [except.spec]")[.](#1.sentence-2) The exception specification is either defined implicitly, or defined explicitly by using a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") as a suffix of a [function declarator](dcl.fct "9.3.4.6 Functions [dcl.fct]")[.](#1.sentence-3) [noexcept-specifier:](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") noexcept ( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ) noexcept [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L774) In a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"), the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]"), if supplied, shall be a contextually converted constant expression of type bool ([[expr.const]](expr.const "7.7 Constant expressions")); that constant expression is the exception specification of the function type in which the [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") appears[.](#2.sentence-1) A ( token that follows noexcept is part of the[*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") and does not commence an initializer ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#2.sentence-2) The [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") noexcept without a [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is equivalent to the [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")noexcept(true)[.](#2.sentence-3) [*Example [1](#example-1)*: void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type boolvoid g() noexcept(sizeof(char)); // OK, conversion of value 1 to type bool is non-narrowing — *end example*] [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L796) If a declaration of a function does not have a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"), 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*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")[.](#3.sentence-1) In an [explicit instantiation](temp.explicit "13.9.3 Explicit instantiation [temp.explicit]") a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") may be specified, but is not required[.](#3.sentence-2) If a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") is specified in an explicit instantiation, the exception specification shall be the same as the exception specification of all other declarations of that function[.](#3.sentence-3) A diagnostic is required only if the exception specifications are not the same within a single translation unit[.](#3.sentence-4) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L817) 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[.](#4.sentence-1) [*Example [2](#example-2)*: struct B {virtual void f() noexcept; virtual void g(); virtual void h() noexcept = delete;}; struct D: B {void f(); // errorvoid g() noexcept; // OKvoid h() = delete; // OK}; The declaration ofD​::​f is ill-formed because it has a potentially-throwing exception specification, whereasB​::​f has a non-throwing exception specification[.](#4.sentence-2) — *end example*] [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L850) An expression E is[*potentially-throwing*](#def:potentially-throwing,expression "14.5 Exception specifications [except.spec]") if - [(5.1)](#5.1) E is a [function call](expr.call "7.6.1.3 Function call [expr.call]") whose [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") has a function type, or a pointer-to-function type, with a potentially-throwing exception specification, or - [(5.2)](#5.2) E implicitly invokes a function (such as an overloaded operator, an allocation function in a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]"), a constructor for a function argument, or a destructor) that has a potentially-throwing exception specification, or - [(5.3)](#5.3) E is a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]") ([[expr.throw]](expr.throw "7.6.18 Throwing an exception")), or - [(5.4)](#5.4) E is a dynamic_cast expression that casts to a reference type and requires a runtime check ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast")), or - [(5.5)](#5.5) E is a typeid expression applied to a (possibly parenthesized) built-in unary * operator applied to a pointer to a polymorphic class type ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")), or - [(5.6)](#5.6) any of the [immediate subexpressions](intro.execution#def:immediate_subexpression "6.10.1 Sequential execution [intro.execution]") of E is potentially-throwing[.](#5.sentence-1) [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L887) An implicitly-declared constructor for a class X, or a constructor without a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") that is defaulted on its first declaration, has a potentially-throwing exception specification if and only if any of the following constructs is potentially-throwing: - [(6.1)](#6.1) the invocation of a constructor selected by overload resolution in the implicit definition of the constructor for class X to initialize a potentially constructed subobject, or - [(6.2)](#6.2) a subexpression of such an initialization, such as a default argument expression, or, - [(6.3)](#6.3) for a default constructor, a default member initializer[.](#6.sentence-1) [*Note [1](#note-1)*: Even though destructors for fully-constructed subobjects are invoked when an exception is thrown during the execution of a constructor ([[except.ctor]](except.ctor "14.3 Stack unwinding")), 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​::​terminate rather than escape the constructor ([[except.throw]](except.throw "14.2 Throwing an exception"), [[except.terminate]](except.terminate "14.6.2 The std​::​terminate function"))[.](#6.sentence-2) — *end note*] [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L917) The exception specification for an implicitly-declared destructor, or a destructor without a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"), 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[.](#7.sentence-1) [8](#8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L927) The exception specification for an implicitly-declared assignment operator, or an assignment-operator without a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") that 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[.](#8.sentence-1) [9](#9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L935) A [deallocation function](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]") with no explicit [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") has a non-throwing exception specification[.](#9.sentence-1) [10](#10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L940) The exception specification for a comparison operator function ([[over.binary]](over.binary "12.4.3 Binary operators")) without a [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") that is defaulted on its first declaration is potentially-throwing if and only if any expression in the implicit definition is potentially-throwing[.](#10.sentence-1) [11](#11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L948) [*Example [3](#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; // implicit exception specification is noexcept(true) B(B&&, int = (throw 42, 0)) noexcept; ~B() noexcept(false);};int n = 7;struct D : public A, public B {int * p = new int[n]; // D​::​D() potentially-throwing, as the new operator may throw bad_alloc or bad_array_new_length// D​::​D(const D&) non-throwing// D​::​D(D&&) potentially-throwing, as the default argument for B's constructor may throw// D​::​~D() potentially-throwing}; 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[.](#11.sentence-1) — *end example*] [12](#12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L981) An exception specification is considered to be [*needed*](#def:needed,exception_specification "14.5 Exception specifications [except.spec]") when: - [(12.1)](#12.1) in an expression, the function is selected by overload resolution ([[over.match]](over.match "12.2 Overload resolution"), [[over.over]](over.over "12.3 Address of an overload set")); - [(12.2)](#12.2) the function is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")); - [(12.3)](#12.3) the exception specification is compared to that of another declaration (e.g., an explicit specialization or an overriding virtual function); - [(12.4)](#12.4) the function is defined; or - [(12.5)](#12.5) the exception specification is needed for a defaulted function that calls the function[.](#12.sentence-1) [*Note [2](#note-2)*: A defaulted declaration does not require the exception specification of a base member function to be evaluated until the implicit exception specification of the derived function is needed, but an explicit [*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") needs the implicit exception specification to compare against[.](#12.5.sentence-2) — *end note*] The exception specification of a defaulted function is evaluated as described above only when needed; similarly, the[*noexcept-specifier*](#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") of a specialization of a templated function is instantiated only when needed[.](#12.sentence-2)