[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)
