Files
cppdraft_translate/cppdraft/except/spec.md
2025-10-25 03:02:53 +03:00

272 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.5Exception 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.5Exception specifications[except.spec]"),
otherwise it has a[*non-throwing exception specification*](#def:non-throwing_exception_specification "14.5Exception 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.5Exception specifications[except.spec]") as a suffix of a [function declarator](dcl.fct "9.3.4.6Functions[dcl.fct]")[.](#1.sentence-3)
[noexcept-specifier:](#nt:noexcept-specifier "14.5Exception specifications[except.spec]")
noexcept ( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant 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.5Exception specifications[except.spec]"), the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]"),
if supplied, shall be a contextually converted constant expression
of type bool ([[expr.const]](expr.const "7.7Constant expressions"));
that constant expression is the exception specification of
the function type in which the [*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception specifications[except.spec]") appears[.](#2.sentence-1)
A ( token that follows noexcept is part of the[*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception specifications[except.spec]") and does not commence an
initializer ([[dcl.init]](dcl.init "9.5Initializers"))[.](#2.sentence-2)
The [*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception specifications[except.spec]") noexcept without a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") is
equivalent to the [*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception 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.5Exception 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.5Exception specifications[except.spec]")[.](#3.sentence-1)
In an [explicit instantiation](temp.explicit "13.9.3Explicit instantiation[temp.explicit]") a [*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception specifications[except.spec]") may be specified,
but is not required[.](#3.sentence-2)
If a [*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception 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.5Exception specifications[except.spec]") if
- [(5.1)](#5.1)
E is a [function call](expr.call "7.6.1.3Function call[expr.call]") whose [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[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.8New[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.18Throwing an exception[expr.throw]") ([[expr.throw]](expr.throw "7.6.18Throwing 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.7Dynamic 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.8Type identification")),
or
- [(5.6)](#5.6)
any of the [immediate subexpressions](intro.execution#def:immediate_subexpression "6.10.1Sequential 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.5Exception 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.3Stack 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.2Throwing an exception"), [[except.terminate]](except.terminate "14.6.2The 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.5Exception 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.5Exception 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.3Deallocation functions[basic.stc.dynamic.deallocation]") with no explicit [*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception 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.3Binary operators"))
without a [*noexcept-specifier*](#nt:noexcept-specifier "14.5Exception 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.5Exception specifications[except.spec]") when:
- [(12.1)](#12.1)
in an expression, the function is selected by
overload resolution ([[over.match]](over.match "12.2Overload resolution"), [[over.over]](over.over "12.3Address of an overload set"));
- [(12.2)](#12.2)
the function is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-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.5Exception 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.5Exception specifications[except.spec]") of a specialization
of a templated function
is instantiated only when needed[.](#12.sentence-2)