Init
This commit is contained in:
155
cppdraft/except/ctor.md
Normal file
155
cppdraft/except/ctor.md
Normal file
@@ -0,0 +1,155 @@
|
||||
[except.ctor]
|
||||
|
||||
# 14 Exception handling [[except]](./#except)
|
||||
|
||||
## 14.3 Stack unwinding [except.ctor]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L386)
|
||||
|
||||
As control passes from the point where an exception is thrown
|
||||
to a handler,
|
||||
objects are destroyed by a process,
|
||||
specified in this subclause, called [*stack unwinding*](#def:stack_unwinding "14.3 Stack unwinding [except.ctor]")[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L393)
|
||||
|
||||
Each object with automatic storage duration is destroyed if it has been
|
||||
constructed, but not yet destroyed,
|
||||
since the try block was entered[.](#2.sentence-1)
|
||||
|
||||
If an exception is thrown during the destruction of temporaries or
|
||||
local variables for a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")),
|
||||
the destructor for the returned object (if any) is also invoked[.](#2.sentence-2)
|
||||
|
||||
The objects are destroyed in the reverse order of the completion
|
||||
of their construction[.](#2.sentence-3)
|
||||
|
||||
[*Example [1](#example-1)*: struct A { };
|
||||
|
||||
struct Y { ~Y() noexcept(false) { throw 0; } };
|
||||
|
||||
A f() {try { A a;
|
||||
Y y;
|
||||
A b; return {}; // #1} catch (...) {}return {}; // #2}
|
||||
|
||||
At #1, the returned object of type A is constructed[.](#2.sentence-4)
|
||||
|
||||
Then, the local variable b is destroyed ([[stmt.jump]](stmt.jump "8.8 Jump statements"))[.](#2.sentence-5)
|
||||
|
||||
Next, the local variable y is destroyed,
|
||||
causing stack unwinding,
|
||||
resulting in the destruction of the returned object,
|
||||
followed by the destruction of the local variable a[.](#2.sentence-6)
|
||||
|
||||
Finally, the returned object is constructed again at #2[.](#2.sentence-7)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L428)
|
||||
|
||||
If the initialization of an object
|
||||
other than by delegating constructor
|
||||
is terminated by an exception,
|
||||
the destructor is invoked for
|
||||
each of the object's subobjects
|
||||
that were known to be initialized by the object's initialization and
|
||||
whose initialization has completed ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
If such an object has a reference member
|
||||
that extends the lifetime of a temporary object,
|
||||
this ends the lifetime of the reference member,
|
||||
so the lifetime of the temporary object is effectively not extended[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A subobject is [*known to be initialized*](#def:known_to_be_initialized "14.3 Stack unwinding [except.ctor]") if it is not an anonymous union member and
|
||||
its initialization is specified
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
in [[class.base.init]](class.base.init "11.9.3 Initializing bases and members") for initialization by constructor,
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
in [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors") for initialization by defaulted copy/move constructor,
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
in [[class.inhctor.init]](class.inhctor.init "11.9.4 Initialization by inherited constructor") for initialization by inherited constructor,
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
in [[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates") for aggregate initialization,
|
||||
|
||||
- [(3.5)](#3.5)
|
||||
|
||||
in [[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures") for the initialization of
|
||||
the closure object when evaluating a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),
|
||||
|
||||
- [(3.6)](#3.6)
|
||||
|
||||
in [[dcl.init.general]](dcl.init.general "9.5.1 General") for
|
||||
default-initialization, value-initialization, or direct-initialization
|
||||
of an array[.](#3.sentence-3)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
This includes virtual base class subobjects
|
||||
if the initialization
|
||||
is for a complete object, and
|
||||
can include variant members
|
||||
that were nominated explicitly by
|
||||
a [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") or [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]") or
|
||||
that have a default member initializer[.](#3.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If the destructor of an object is terminated by an exception,
|
||||
each destructor invocation
|
||||
that would be performed after executing the body of the destructor ([[class.dtor]](class.dtor "11.4.7 Destructors")) and
|
||||
that has not yet begun execution
|
||||
is performed[.](#3.sentence-5)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
This includes virtual base class subobjects if
|
||||
the destructor was invoked for a complete object[.](#3.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
The subobjects are destroyed in the reverse order of the completion of
|
||||
their construction[.](#3.sentence-7)
|
||||
|
||||
Such destruction is sequenced before entering a
|
||||
handler of the [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of the constructor or destructor,
|
||||
if any[.](#3.sentence-8)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L480)
|
||||
|
||||
If the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of the [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") of a delegating constructor
|
||||
for an object exits via
|
||||
an exception, the object's destructor is invoked[.](#4.sentence-1)
|
||||
|
||||
Such destruction is sequenced before entering a handler of the[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of a delegating constructor for that object, if any[.](#4.sentence-2)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L489)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
If the object was allocated by a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
|
||||
the matching [deallocation function](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]"),
|
||||
if any, is called to free the storage occupied by the object[.](#5.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
237
cppdraft/except/handle.md
Normal file
237
cppdraft/except/handle.md
Normal file
@@ -0,0 +1,237 @@
|
||||
[except.handle]
|
||||
|
||||
# 14 Exception handling [[except]](./#except)
|
||||
|
||||
## 14.4 Handling an exception [except.handle]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L500)
|
||||
|
||||
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") in a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") describes the type(s) of exceptions that can cause
|
||||
that[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") to be entered[.](#1.sentence-1)
|
||||
|
||||
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") shall not denote an incomplete type, an abstract class type, or an rvalue reference type[.](#1.sentence-2)
|
||||
|
||||
The[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") shall not denote a pointer or reference to an
|
||||
incomplete type, other than âpointer to cv voidâ[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L521)
|
||||
|
||||
A handler of typeâarray of Tâ orfunction type T is adjusted to be of type
|
||||
âpointer to Tâ[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L530)
|
||||
|
||||
A[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is a match for
|
||||
an exception object
|
||||
of typeE if
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
The [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T orcv T& andE and T are the same type (ignoring the top-level [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s*), or
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
the [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T orcv T& andT is an unambiguous public base class of E, or
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
the [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T or const T& where T is a pointer or pointer-to-member type andE is a pointer or pointer-to-member type
|
||||
that can be converted to T by one or more of
|
||||
* [(3.3.1)](#3.3.1)
|
||||
|
||||
a standard [pointer conversion](conv.ptr "7.3.12 Pointer conversions [conv.ptr]") not involving conversions
|
||||
to pointers to private or protected or ambiguous classes
|
||||
|
||||
* [(3.3.2)](#3.3.2)
|
||||
|
||||
a [function pointer conversion](conv.fctptr "7.3.14 Function pointer conversions [conv.fctptr]")
|
||||
|
||||
* [(3.3.3)](#3.3.3)
|
||||
|
||||
a [qualification conversion](conv.qual "7.3.6 Qualification conversions [conv.qual]"), or
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
the [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") is of type cv T or const T& where T is a pointer or pointer-to-member type and E is std::nullptr_t[.](#3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A[*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]") whose operand is an integer literal with value zero does not match a handler of
|
||||
pointer or pointer-to-member type[.](#3.sentence-2)
|
||||
|
||||
A handler of reference to array or function type
|
||||
is never a match for any exception object ([[expr.throw]](expr.throw "7.6.18 Throwing an exception"))[.](#3.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*: class Matherr { /* ... */ virtual void vf(); };class Overflow: public Matherr { /* ... */ };class Underflow: public Matherr { /* ... */ };class Zerodivide: public Matherr { /* ... */ };
|
||||
|
||||
void f() {try { g(); } catch (Overflow oo) {// ...} catch (Matherr mm) {// ...}}
|
||||
|
||||
Here, theOverflow handler will catch exceptions of typeOverflow and theMatherr handler will catch exceptions of typeMatherr and of all types publicly derived fromMatherr including exceptions of typeUnderflow andZerodivide[.](#3.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L611)
|
||||
|
||||
The handlers for a try block are tried in order of appearance[.](#4.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
This makes it possible to write handlers that can never be
|
||||
executed, for example by placing a handler for a final derived class after
|
||||
a handler for a corresponding unambiguous public base class[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L619)
|
||||
|
||||
A... in a handler's[*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") specifies a match for any exception[.](#5.sentence-1)
|
||||
|
||||
If present, a... handler shall be the last handler for its try block[.](#5.sentence-2)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L629)
|
||||
|
||||
If no match is found among the handlers for a try block,
|
||||
the search for a matching
|
||||
handler continues in a dynamically surrounding try block
|
||||
of the same thread[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L635)
|
||||
|
||||
If the search for a handler
|
||||
exits the function body of a function with a
|
||||
non-throwing exception specification,
|
||||
the function std::terminate ([[except.terminate]](except.terminate "14.6.2 The std::terminate function")) is invoked[.](#7.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
An implementation is not permitted to reject an expression merely because, when
|
||||
executed, it throws or might
|
||||
throw an exception from a function with a non-throwing exception specification[.](#7.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#example-2)*: extern void f(); // potentially-throwingvoid g() noexcept { f(); // valid, even if f throwsthrow 42; // valid, effectively a call to std::terminate}
|
||||
|
||||
The call tof is well-formed despite the possibility for it to throw an exception[.](#7.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L661)
|
||||
|
||||
If no matching handler is found,
|
||||
the function std::terminate is invoked;
|
||||
whether or not the stack is unwound before this invocation ofstd::terminate is implementation-defined ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))[.](#8.sentence-1)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L669)
|
||||
|
||||
A handler is considered [*active*](#def:exception_handling,handler,active "14.4 Handling an exception [except.handle]") when
|
||||
initialization is complete for the parameter (if any) of the catch clause[.](#9.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The stack will have been unwound at that point[.](#9.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Also, an implicit handler is considered active when
|
||||
the function std::terminate is entered due to a throw[.](#9.sentence-3)
|
||||
|
||||
A handler is no longer considered active when the
|
||||
catch clause exits[.](#9.sentence-4)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L680)
|
||||
|
||||
The exception with the most recently activated handler that is
|
||||
still active is called the[*currently handled exception*](#def:exception_handling,currently_handled_exception "14.4 Handling an exception [except.handle]")[.](#10.sentence-1)
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L686)
|
||||
|
||||
Referring to any non-static member or base class of an object
|
||||
in the handler for a[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of a constructor or destructor for that object results in undefined behavior[.](#11.sentence-1)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L692)
|
||||
|
||||
Exceptions thrown in destructors of objects with static storage duration or in
|
||||
constructors of objects associated with non-block variables with static storage duration are not caught by a[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") on
|
||||
the [main function](basic.start.main "6.10.3.1 main function [basic.start.main]")[.](#12.sentence-1)
|
||||
|
||||
Exceptions thrown in destructors of objects with thread storage duration or in constructors of objects associated with non-block variables with thread storage duration are not caught by a[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") on the initial function of the thread[.](#12.sentence-2)
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L702)
|
||||
|
||||
If a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")) appears in a handler of the[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of a
|
||||
constructor, the program is ill-formed[.](#13.sentence-1)
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L708)
|
||||
|
||||
The currently handled exception
|
||||
is rethrown if control reaches the end of a handler of the[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") of a constructor or destructor[.](#14.sentence-1)
|
||||
|
||||
Otherwise, flowing off the end of
|
||||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") of a [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") is equivalent to flowing off the end of
|
||||
the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of that function (see [[stmt.return]](stmt.return "8.8.4 The return statement"))[.](#14.sentence-2)
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L721)
|
||||
|
||||
The variable declared by the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]"), of typecv T or cv T&, is initialized from the exception object,
|
||||
of type E, as follows:
|
||||
|
||||
- [(15.1)](#15.1)
|
||||
|
||||
if T is a base class of E,
|
||||
the variable is copy-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||||
from an lvalue of type T designating the corresponding base class subobject
|
||||
of the exception object;
|
||||
|
||||
- [(15.2)](#15.2)
|
||||
|
||||
otherwise, the variable is copy-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||||
from an lvalue of type E designating the exception object[.](#15.sentence-1)
|
||||
|
||||
The lifetime of the variable ends
|
||||
when the handler exits, after the
|
||||
destruction of any objects with automatic storage duration initialized
|
||||
within the handler[.](#15.sentence-2)
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L740)
|
||||
|
||||
When the handler declares an object,
|
||||
any changes to that object will not affect the exception object[.](#16.sentence-1)
|
||||
|
||||
When the handler declares a reference to an object,
|
||||
any changes to the referenced object are changes to the
|
||||
exception object and will have effect should that object be rethrown[.](#16.sentence-2)
|
||||
108
cppdraft/except/nested.md
Normal file
108
cppdraft/except/nested.md
Normal file
@@ -0,0 +1,108 @@
|
||||
[except.nested]
|
||||
|
||||
# 17 Language support library [[support]](./#support)
|
||||
|
||||
## 17.9 Exception handling [[support.exception]](support.exception#except.nested)
|
||||
|
||||
### 17.9.8 nested_exception [except.nested]
|
||||
|
||||
[ð](#lib:nested_exception)
|
||||
|
||||
namespace std {class nested_exception {public:constexpr nested_exception() noexcept; constexpr nested_exception(const nested_exception&) noexcept = default; constexpr nested_exception& operator=(const nested_exception&) noexcept = default; constexpr virtual ~nested_exception() = default; // access functions[[noreturn]] constexpr void rethrow_nested() const; constexpr exception_ptr nested_ptr() const noexcept; }; template<class T> [[noreturn]] constexpr void throw_with_nested(T&& t); template<class E> constexpr void rethrow_if_nested(const E& e);}
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4297)
|
||||
|
||||
The class nested_exception is designed for use as a mixin through
|
||||
multiple inheritance[.](#1.sentence-1)
|
||||
|
||||
It captures the currently handled exception and stores it
|
||||
for later use[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4302)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
nested_exception has a virtual destructor to make it a
|
||||
polymorphic class[.](#2.sentence-1)
|
||||
|
||||
Its presence can be tested for with dynamic_cast[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[ð](#lib:nested_exception,constructor)
|
||||
|
||||
`constexpr nested_exception() noexcept;
|
||||
`
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4314)
|
||||
|
||||
*Effects*: The constructor calls current_exception() and stores the returned value[.](#3.sentence-1)
|
||||
|
||||
[ð](#lib:rethrow_nested,nested_exception)
|
||||
|
||||
`[[noreturn]] constexpr void rethrow_nested() const;
|
||||
`
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4325)
|
||||
|
||||
*Effects*: If nested_ptr() returns a null pointer, the function calls the function std::terminate[.](#4.sentence-1)
|
||||
|
||||
Otherwise, it throws the stored exception captured by *this[.](#4.sentence-2)
|
||||
|
||||
[ð](#lib:nested_ptr,nested_exception)
|
||||
|
||||
`constexpr exception_ptr nested_ptr() const noexcept;
|
||||
`
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4337)
|
||||
|
||||
*Returns*: The stored exception captured by this nested_exception object[.](#5.sentence-1)
|
||||
|
||||
[ð](#lib:throw_with_nested,nested_exception)
|
||||
|
||||
`template<class T> [[noreturn]] constexpr void throw_with_nested(T&& t);
|
||||
`
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4348)
|
||||
|
||||
Let U be decay_t<T>[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4351)
|
||||
|
||||
*Preconditions*: U meets the [*Cpp17CopyConstructible*](utility.arg.requirements#:Cpp17CopyConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4355)
|
||||
|
||||
*Throws*: If is_class_v<U> && !is_final_v<U> && !is_base_of_v<nested_exception, U> is true,
|
||||
an exception of unspecified type that is publicly derived from bothU and nested_exception and constructed from std::forward<T>(t), otherwisestd::forward<T>(t)[.](#8.sentence-1)
|
||||
|
||||
[ð](#lib:rethrow_if_nested,nested_exception)
|
||||
|
||||
`template<class E> constexpr void rethrow_if_nested(const E& e);
|
||||
`
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4371)
|
||||
|
||||
*Effects*: If E is not a polymorphic class type, or
|
||||
if nested_exception is an inaccessible or ambiguous base class of E,
|
||||
there is no effect[.](#9.sentence-1)
|
||||
|
||||
Otherwise, performs:if (auto p = dynamic_cast<const nested_exception*>(addressof(e))) p->rethrow_nested();
|
||||
99
cppdraft/except/pre.md
Normal file
99
cppdraft/except/pre.md
Normal file
@@ -0,0 +1,99 @@
|
||||
[except.pre]
|
||||
|
||||
# 14 Exception handling [[except]](./#except)
|
||||
|
||||
## 14.1 Preamble [except.pre]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L12)
|
||||
|
||||
Exception handling provides a way of transferring control and information
|
||||
from a point in the execution of a thread to an exception handler
|
||||
associated with a point previously passed by the execution[.](#1.sentence-1)
|
||||
|
||||
A handler will be invoked only by throwing an exception
|
||||
in code executed in the handler's try block
|
||||
or in functions called from the handler's try block[.](#1.sentence-2)
|
||||
|
||||
[try-block:](#nt:try-block "14.1 Preamble [except.pre]")
|
||||
try [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") [*handler-seq*](#nt:handler-seq "14.1 Preamble [except.pre]")
|
||||
|
||||
[function-try-block:](#nt:function-try-block "14.1 Preamble [except.pre]")
|
||||
try [*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") [*handler-seq*](#nt:handler-seq "14.1 Preamble [except.pre]")
|
||||
|
||||
[handler-seq:](#nt:handler-seq "14.1 Preamble [except.pre]")
|
||||
[*handler*](#nt:handler "14.1 Preamble [except.pre]") [*handler-seq*](#nt:handler-seq "14.1 Preamble [except.pre]")opt
|
||||
|
||||
[handler:](#nt:handler "14.1 Preamble [except.pre]")
|
||||
catch ( [*exception-declaration*](#nt:exception-declaration "14.1 Preamble [except.pre]") ) [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")
|
||||
|
||||
[exception-declaration:](#nt:exception-declaration "14.1 Preamble [except.pre]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt
|
||||
...
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in an [*exception-declaration*](#nt:exception-declaration "14.1 Preamble [except.pre]") appertains to the parameter of the catch clause ([[except.handle]](except.handle "14.4 Handling an exception"))[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L56)
|
||||
|
||||
A [*try-block*](#nt:try-block "14.1 Preamble [except.pre]") is a [*statement*](stmt.pre#nt:statement "8.1 Preamble [stmt.pre]") ([[stmt.pre]](stmt.pre "8.1 Preamble"))[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Within this Clause
|
||||
âtry blockâ is taken to mean both [*try-block*](#nt:try-block "14.1 Preamble [except.pre]") and[*function-try-block*](#nt:function-try-block "14.1 Preamble [except.pre]")[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L68)
|
||||
|
||||
The [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of a try block or of a handler is a
|
||||
control-flow-limited statement ([[stmt.label]](stmt.label "8.2 Label"))[.](#3.sentence-1)
|
||||
|
||||
[*Example [1](#example-1)*: void f() {goto l1; // errorgoto l2; // errortry {goto l1; // OKgoto l2; // error l1: ; } catch (...) { l2: ; goto l1; // errorgoto l2; // OK}} â *end example*]
|
||||
|
||||
Agoto,break,return,
|
||||
orcontinue statement can be used to transfer control out of
|
||||
a try block or handler[.](#3.sentence-2)
|
||||
|
||||
When this happens, each variable declared in the try block
|
||||
will be destroyed in the context that
|
||||
directly contains its declaration[.](#3.sentence-3)
|
||||
|
||||
[*Example [2](#example-2)*: lab: try { T1 t1; try { T2 t2; if ([*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]"))goto lab; } catch(...) { /* handler 2 */ }} catch(...) { /* handler 1 */ }
|
||||
|
||||
Here, executinggoto lab; will destroy firstt2,
|
||||
thent1,
|
||||
assuming the[*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]") does not declare a variable[.](#3.sentence-4)
|
||||
|
||||
Any exception thrown while destroyingt2 will result in executinghandler 2;
|
||||
any exception thrown while destroyingt1 will result in executinghandler 1[.](#3.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L144)
|
||||
|
||||
A[*function-try-block*](#nt:function-try-block "14.1 Preamble [except.pre]") associates a[*handler-seq*](#nt:handler-seq "14.1 Preamble [except.pre]") with the[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]"),
|
||||
if present, and the[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")[.](#4.sentence-1)
|
||||
|
||||
An exception
|
||||
thrown during the execution of the[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") or, for constructors and destructors, during the initialization or
|
||||
destruction, respectively, of the class's subobjects,
|
||||
transfers control to a handler in a[*function-try-block*](#nt:function-try-block "14.1 Preamble [except.pre]") in the same way as an exception thrown during the execution of a[*try-block*](#nt:try-block "14.1 Preamble [except.pre]") transfers control to other handlers[.](#4.sentence-2)
|
||||
|
||||
[*Example [3](#example-3)*: int f(int);class C {int i; double d;public: C(int, double);};
|
||||
|
||||
C::C(int ii, double id)try : i(f(ii)), d(id) {// constructor statements} catch (...) {// handles exceptions thrown from the ctor-initializer and from the constructor statements} â *end example*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L184)
|
||||
|
||||
In this Clause, âbeforeâ and âafterâ refer to the[âsequenced beforeâ](intro.execution#def:sequenced_before "6.10.1 Sequential execution [intro.execution]") relation[.](#5.sentence-1)
|
||||
271
cppdraft/except/spec.md
Normal file
271
cppdraft/except/spec.md
Normal file
@@ -0,0 +1,271 @@
|
||||
[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)
|
||||
172
cppdraft/except/special.md
Normal file
172
cppdraft/except/special.md
Normal file
@@ -0,0 +1,172 @@
|
||||
[except.special]
|
||||
|
||||
# 14 Exception handling [[except]](./#except)
|
||||
|
||||
## 14.6 Special functions [except.special]
|
||||
|
||||
### [14.6.1](#general) General [[except.special.general]](except.special.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L1017)
|
||||
|
||||
The function std::terminate ([[except.terminate]](#except.terminate "14.6.2 The std::terminate function"))
|
||||
is used by the exception
|
||||
handling mechanism for coping with errors related to the exception handling
|
||||
mechanism itself[.](#general-1.sentence-1)
|
||||
|
||||
The function std::uncaught_exceptions ([[uncaught.exceptions]](uncaught.exceptions "17.9.6 uncaught_exceptions"))
|
||||
reports how many exceptions are uncaught in the current thread[.](#general-1.sentence-2)
|
||||
|
||||
The function std::current_exception ([[propagation]](propagation "17.9.7 Exception propagation")) and the classstd::nested_exception ([[except.nested]](except.nested "17.9.8 nested_exception")) can be used by a program to
|
||||
capture the currently handled exception[.](#general-1.sentence-3)
|
||||
|
||||
### [14.6.2](#except.terminate) The std::terminate function [[except.terminate]](except.terminate)
|
||||
|
||||
[1](#except.terminate-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L1030)
|
||||
|
||||
Some errors in a program cannot be recovered from, such as when an exception
|
||||
is not handled or a std::thread object is destroyed while its thread
|
||||
function is still executing[.](#except.terminate-1.sentence-1)
|
||||
|
||||
In such cases,
|
||||
the function std::terminate ([[exception.terminate]](exception.terminate "17.9.5 Abnormal termination")) is invoked[.](#except.terminate-1.sentence-2)
|
||||
|
||||
[*Note [1](#except.terminate-note-1)*:
|
||||
|
||||
These situations are:
|
||||
|
||||
- [(1.1)](#except.terminate-1.1)
|
||||
|
||||
when the exception handling mechanism, after completing
|
||||
the initialization of the exception object
|
||||
but before
|
||||
activation of a handler for the exception ([[except.throw]](except.throw "14.2 Throwing an exception")),
|
||||
calls a function that exits
|
||||
via an exception, or
|
||||
|
||||
- [(1.2)](#except.terminate-1.2)
|
||||
|
||||
when the exception handling mechanism cannot find a handler for a thrown exception ([[except.handle]](except.handle "14.4 Handling an exception")), or
|
||||
|
||||
- [(1.3)](#except.terminate-1.3)
|
||||
|
||||
when the search for a [handler](except.handle "14.4 Handling an exception [except.handle]") exits the function body of a function
|
||||
with a non-throwing [exception specification](except.spec "14.5 Exception specifications [except.spec]"),
|
||||
including when a contract-violation handler
|
||||
invoked from an evaluation of
|
||||
a function contract assertion ([[basic.contract.eval]](basic.contract.eval "6.11.2 Evaluation")) associated with the function
|
||||
exits via an exception,
|
||||
or
|
||||
|
||||
- [(1.4)](#except.terminate-1.4)
|
||||
|
||||
when the destruction of an object during [stack unwinding](except.ctor#def:stack_unwinding "14.3 Stack unwinding [except.ctor]") terminates by throwing an exception, or
|
||||
|
||||
- [(1.5)](#except.terminate-1.5)
|
||||
|
||||
when initialization of a non-block
|
||||
variable with static or thread storage duration ([[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"))
|
||||
exits via an exception, or
|
||||
|
||||
- [(1.6)](#except.terminate-1.6)
|
||||
|
||||
when destruction of an object with static or thread storage duration exits
|
||||
via an exception ([[basic.start.term]](basic.start.term "6.10.3.4 Termination")), or
|
||||
|
||||
- [(1.7)](#except.terminate-1.7)
|
||||
|
||||
when execution of a function registered withstd::atexit or std::at_quick_exit exits via an exception ([[support.start.term]](support.start.term "17.5 Startup and termination")), or
|
||||
|
||||
- [(1.8)](#except.terminate-1.8)
|
||||
|
||||
when 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"))
|
||||
with no operand attempts to rethrow an exception and no exception is being
|
||||
handled ([[except.throw]](except.throw "14.2 Throwing an exception")), or
|
||||
|
||||
- [(1.9)](#except.terminate-1.9)
|
||||
|
||||
when the function std::nested_exception::rethrow_nested is called for an object
|
||||
that has captured no exception ([[except.nested]](except.nested "17.9.8 nested_exception")), or
|
||||
|
||||
- [(1.10)](#except.terminate-1.10)
|
||||
|
||||
when execution of the initial function of a thread exits via
|
||||
an exception ([[thread.thread.constr]](thread.thread.constr "32.4.3.3 Constructors")), or
|
||||
|
||||
- [(1.11)](#except.terminate-1.11)
|
||||
|
||||
for a parallel algorithm whose ExecutionPolicy specifies such
|
||||
behavior ([[execpol.seq]](execpol.seq "26.3.6.3 Sequenced execution policy"), [[execpol.par]](execpol.par "26.3.6.4 Parallel execution policy"), [[execpol.parunseq]](execpol.parunseq "26.3.6.5 Parallel and unsequenced execution policy")),
|
||||
when execution of an element access function ([[algorithms.parallel.defns]](algorithms.parallel.defns "26.3.1 Preamble"))
|
||||
of the parallel algorithm exits via an exception ([[algorithms.parallel.exceptions]](algorithms.parallel.exceptions "26.3.4 Parallel algorithm exceptions")), or
|
||||
|
||||
- [(1.12)](#except.terminate-1.12)
|
||||
|
||||
when the destructor or the move assignment operator is invoked on an object
|
||||
of type std::thread that refers to
|
||||
a joinable thread ([[thread.thread.destr]](thread.thread.destr "32.4.3.4 Destructor"), [[thread.thread.assign]](thread.thread.assign "32.4.3.5 Assignment")), or
|
||||
|
||||
- [(1.13)](#except.terminate-1.13)
|
||||
|
||||
when a call to a wait(), wait_until(), or wait_for() function on a condition variable ([[thread.condition.condvar]](thread.condition.condvar "32.7.4 Class condition_variable"), [[thread.condition.condvarany]](thread.condition.condvarany "32.7.5 Class condition_variable_any"))
|
||||
fails to meet a postcondition, or
|
||||
|
||||
- [(1.14)](#except.terminate-1.14)
|
||||
|
||||
when a callback invocation exits via an exception
|
||||
when requesting stop on
|
||||
a std::stop_source or
|
||||
a std::inplace_stop_source ([[stopsource.mem]](stopsource.mem "32.3.5.3 Member functions"), [[stopsource.inplace.mem]](stopsource.inplace.mem "32.3.9.3 Member functions")),
|
||||
or in the constructor ofstd::stop_callback orstd::inplace_stop_callback ([[stopcallback.cons]](stopcallback.cons "32.3.6.2 Constructors and destructor"), [[stopcallback.inplace.cons]](stopcallback.inplace.cons "32.3.10.2 Constructors and destructor"))
|
||||
when a callback invocation exits via an exception, or
|
||||
|
||||
- [(1.15)](#except.terminate-1.15)
|
||||
|
||||
when a run_loop object is destroyed
|
||||
that is still in the running state ([[exec.run.loop]](exec.run.loop "33.12.1 execution::run_loop")), or
|
||||
|
||||
- [(1.16)](#except.terminate-1.16)
|
||||
|
||||
when unhandled_stopped is called on
|
||||
a with_awaitable_senders<T> object ([[exec.with.awaitable.senders]](exec.with.awaitable.senders "33.13.2 execution::with_awaitable_senders"))
|
||||
whose continuation is not a handle to a coroutine
|
||||
whose promise type has an unhandled_stopped member function, or
|
||||
|
||||
- [(1.17)](#except.terminate-1.17)
|
||||
|
||||
when an object scope of typestd::execution::simple_counting_scope orstd::execution::counting_scope is destroyed andscope.*state* is not equal to*joined*,*unused*, or*unused-and-closed* ([[exec.simple.counting.ctor]](exec.simple.counting.ctor "33.14.2.2.2 Constructor and Destructor")), or
|
||||
|
||||
- [(1.18)](#except.terminate-1.18)
|
||||
|
||||
when std::execution::get_parallel_scheduler is called andstd::execution::system_context_replaceability::query_parallel_scheduler_backend() returns a null pointer value ([[exec.par.scheduler]](exec.par.scheduler "33.15 Parallel scheduler")), or
|
||||
|
||||
- [(1.19)](#except.terminate-1.19)
|
||||
|
||||
when an exception is thrown from a coroutine std::execution::task ([[exec.task]](exec.task "33.13.6 execution::task"))
|
||||
which doesn't support a std::execution::set_error_t(std::exception_ptr) completion[.](#except.terminate-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#except.terminate-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L1149)
|
||||
|
||||
In the situation where no matching handler is found, it isimplementation-defined
|
||||
whether or not the stack is unwound
|
||||
before std::terminate is invoked[.](#except.terminate-2.sentence-1)
|
||||
|
||||
In the situation where the search for a handler ([[except.handle]](except.handle "14.4 Handling an exception"))
|
||||
exits the function body of a function
|
||||
with a non-throwing exception specification ([[except.spec]](except.spec "14.5 Exception specifications")), it isimplementation-defined
|
||||
whether the stack is unwound, unwound partially, or not unwound at all
|
||||
before the function std::terminate is invoked[.](#except.terminate-2.sentence-2)
|
||||
|
||||
In all other situations, the stack shall not be unwound before
|
||||
the function std::terminate is invoked[.](#except.terminate-2.sentence-3)
|
||||
|
||||
An implementation is not permitted to finish stack unwinding
|
||||
prematurely based on a determination that the unwind process
|
||||
will eventually cause an invocation of the functionstd::terminate[.](#except.terminate-2.sentence-4)
|
||||
22
cppdraft/except/special/general.md
Normal file
22
cppdraft/except/special/general.md
Normal file
@@ -0,0 +1,22 @@
|
||||
[except.special.general]
|
||||
|
||||
# 14 Exception handling [[except]](./#except)
|
||||
|
||||
## 14.6 Special functions [[except.special]](except.special#general)
|
||||
|
||||
### 14.6.1 General [except.special.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L1017)
|
||||
|
||||
The function std::terminate ([[except.terminate]](except.terminate "14.6.2 The std::terminate function"))
|
||||
is used by the exception
|
||||
handling mechanism for coping with errors related to the exception handling
|
||||
mechanism itself[.](#1.sentence-1)
|
||||
|
||||
The function std::uncaught_exceptions ([[uncaught.exceptions]](uncaught.exceptions "17.9.6 uncaught_exceptions"))
|
||||
reports how many exceptions are uncaught in the current thread[.](#1.sentence-2)
|
||||
|
||||
The function std::current_exception ([[propagation]](propagation "17.9.7 Exception propagation")) and the classstd::nested_exception ([[except.nested]](except.nested "17.9.8 nested_exception")) can be used by a program to
|
||||
capture the currently handled exception[.](#1.sentence-3)
|
||||
155
cppdraft/except/terminate.md
Normal file
155
cppdraft/except/terminate.md
Normal file
@@ -0,0 +1,155 @@
|
||||
[except.terminate]
|
||||
|
||||
# 14 Exception handling [[except]](./#except)
|
||||
|
||||
## 14.6 Special functions [[except.special]](except.special#except.terminate)
|
||||
|
||||
### 14.6.2 The std::terminate function [except.terminate]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L1030)
|
||||
|
||||
Some errors in a program cannot be recovered from, such as when an exception
|
||||
is not handled or a std::thread object is destroyed while its thread
|
||||
function is still executing[.](#1.sentence-1)
|
||||
|
||||
In such cases,
|
||||
the function std::terminate ([[exception.terminate]](exception.terminate "17.9.5 Abnormal termination")) is invoked[.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
These situations are:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
when the exception handling mechanism, after completing
|
||||
the initialization of the exception object
|
||||
but before
|
||||
activation of a handler for the exception ([[except.throw]](except.throw "14.2 Throwing an exception")),
|
||||
calls a function that exits
|
||||
via an exception, or
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
when the exception handling mechanism cannot find a handler for a thrown exception ([[except.handle]](except.handle "14.4 Handling an exception")), or
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
when the search for a [handler](except.handle "14.4 Handling an exception [except.handle]") exits the function body of a function
|
||||
with a non-throwing [exception specification](except.spec "14.5 Exception specifications [except.spec]"),
|
||||
including when a contract-violation handler
|
||||
invoked from an evaluation of
|
||||
a function contract assertion ([[basic.contract.eval]](basic.contract.eval "6.11.2 Evaluation")) associated with the function
|
||||
exits via an exception,
|
||||
or
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
when the destruction of an object during [stack unwinding](except.ctor#def:stack_unwinding "14.3 Stack unwinding [except.ctor]") terminates by throwing an exception, or
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
when initialization of a non-block
|
||||
variable with static or thread storage duration ([[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"))
|
||||
exits via an exception, or
|
||||
|
||||
- [(1.6)](#1.6)
|
||||
|
||||
when destruction of an object with static or thread storage duration exits
|
||||
via an exception ([[basic.start.term]](basic.start.term "6.10.3.4 Termination")), or
|
||||
|
||||
- [(1.7)](#1.7)
|
||||
|
||||
when execution of a function registered withstd::atexit or std::at_quick_exit exits via an exception ([[support.start.term]](support.start.term "17.5 Startup and termination")), or
|
||||
|
||||
- [(1.8)](#1.8)
|
||||
|
||||
when 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"))
|
||||
with no operand attempts to rethrow an exception and no exception is being
|
||||
handled ([[except.throw]](except.throw "14.2 Throwing an exception")), or
|
||||
|
||||
- [(1.9)](#1.9)
|
||||
|
||||
when the function std::nested_exception::rethrow_nested is called for an object
|
||||
that has captured no exception ([[except.nested]](except.nested "17.9.8 nested_exception")), or
|
||||
|
||||
- [(1.10)](#1.10)
|
||||
|
||||
when execution of the initial function of a thread exits via
|
||||
an exception ([[thread.thread.constr]](thread.thread.constr "32.4.3.3 Constructors")), or
|
||||
|
||||
- [(1.11)](#1.11)
|
||||
|
||||
for a parallel algorithm whose ExecutionPolicy specifies such
|
||||
behavior ([[execpol.seq]](execpol.seq "26.3.6.3 Sequenced execution policy"), [[execpol.par]](execpol.par "26.3.6.4 Parallel execution policy"), [[execpol.parunseq]](execpol.parunseq "26.3.6.5 Parallel and unsequenced execution policy")),
|
||||
when execution of an element access function ([[algorithms.parallel.defns]](algorithms.parallel.defns "26.3.1 Preamble"))
|
||||
of the parallel algorithm exits via an exception ([[algorithms.parallel.exceptions]](algorithms.parallel.exceptions "26.3.4 Parallel algorithm exceptions")), or
|
||||
|
||||
- [(1.12)](#1.12)
|
||||
|
||||
when the destructor or the move assignment operator is invoked on an object
|
||||
of type std::thread that refers to
|
||||
a joinable thread ([[thread.thread.destr]](thread.thread.destr "32.4.3.4 Destructor"), [[thread.thread.assign]](thread.thread.assign "32.4.3.5 Assignment")), or
|
||||
|
||||
- [(1.13)](#1.13)
|
||||
|
||||
when a call to a wait(), wait_until(), or wait_for() function on a condition variable ([[thread.condition.condvar]](thread.condition.condvar "32.7.4 Class condition_variable"), [[thread.condition.condvarany]](thread.condition.condvarany "32.7.5 Class condition_variable_any"))
|
||||
fails to meet a postcondition, or
|
||||
|
||||
- [(1.14)](#1.14)
|
||||
|
||||
when a callback invocation exits via an exception
|
||||
when requesting stop on
|
||||
a std::stop_source or
|
||||
a std::inplace_stop_source ([[stopsource.mem]](stopsource.mem "32.3.5.3 Member functions"), [[stopsource.inplace.mem]](stopsource.inplace.mem "32.3.9.3 Member functions")),
|
||||
or in the constructor ofstd::stop_callback orstd::inplace_stop_callback ([[stopcallback.cons]](stopcallback.cons "32.3.6.2 Constructors and destructor"), [[stopcallback.inplace.cons]](stopcallback.inplace.cons "32.3.10.2 Constructors and destructor"))
|
||||
when a callback invocation exits via an exception, or
|
||||
|
||||
- [(1.15)](#1.15)
|
||||
|
||||
when a run_loop object is destroyed
|
||||
that is still in the running state ([[exec.run.loop]](exec.run.loop "33.12.1 execution::run_loop")), or
|
||||
|
||||
- [(1.16)](#1.16)
|
||||
|
||||
when unhandled_stopped is called on
|
||||
a with_awaitable_senders<T> object ([[exec.with.awaitable.senders]](exec.with.awaitable.senders "33.13.2 execution::with_awaitable_senders"))
|
||||
whose continuation is not a handle to a coroutine
|
||||
whose promise type has an unhandled_stopped member function, or
|
||||
|
||||
- [(1.17)](#1.17)
|
||||
|
||||
when an object scope of typestd::execution::simple_counting_scope orstd::execution::counting_scope is destroyed andscope.*state* is not equal to*joined*,*unused*, or*unused-and-closed* ([[exec.simple.counting.ctor]](exec.simple.counting.ctor "33.14.2.2.2 Constructor and Destructor")), or
|
||||
|
||||
- [(1.18)](#1.18)
|
||||
|
||||
when std::execution::get_parallel_scheduler is called andstd::execution::system_context_replaceability::query_parallel_scheduler_backend() returns a null pointer value ([[exec.par.scheduler]](exec.par.scheduler "33.15 Parallel scheduler")), or
|
||||
|
||||
- [(1.19)](#1.19)
|
||||
|
||||
when an exception is thrown from a coroutine std::execution::task ([[exec.task]](exec.task "33.13.6 execution::task"))
|
||||
which doesn't support a std::execution::set_error_t(std::exception_ptr) completion[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L1149)
|
||||
|
||||
In the situation where no matching handler is found, it isimplementation-defined
|
||||
whether or not the stack is unwound
|
||||
before std::terminate is invoked[.](#2.sentence-1)
|
||||
|
||||
In the situation where the search for a handler ([[except.handle]](except.handle "14.4 Handling an exception"))
|
||||
exits the function body of a function
|
||||
with a non-throwing exception specification ([[except.spec]](except.spec "14.5 Exception specifications")), it isimplementation-defined
|
||||
whether the stack is unwound, unwound partially, or not unwound at all
|
||||
before the function std::terminate is invoked[.](#2.sentence-2)
|
||||
|
||||
In all other situations, the stack shall not be unwound before
|
||||
the function std::terminate is invoked[.](#2.sentence-3)
|
||||
|
||||
An implementation is not permitted to finish stack unwinding
|
||||
prematurely based on a determination that the unwind process
|
||||
will eventually cause an invocation of the functionstd::terminate[.](#2.sentence-4)
|
||||
176
cppdraft/except/throw.md
Normal file
176
cppdraft/except/throw.md
Normal file
@@ -0,0 +1,176 @@
|
||||
[except.throw]
|
||||
|
||||
# 14 Exception handling [[except]](./#except)
|
||||
|
||||
## 14.2 Throwing an exception [except.throw]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L192)
|
||||
|
||||
Throwing an exception transfers control to a handler[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
An exception can be thrown from one of the following contexts:[*throw-expression*](expr.throw#nt:throw-expression "7.6.18 Throwing an exception [expr.throw]")*s* ([[expr.throw]](expr.throw "7.6.18 Throwing an exception")),
|
||||
allocation functions ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")),dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast")),typeid ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]")*s* ([[expr.new]](expr.new "7.6.2.8 New")), and standard library
|
||||
functions ([[structure.specifications]](structure.specifications "16.3.2.4 Detailed specifications"))[.](#1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
An object is passed and the type of that object determines which handlers
|
||||
can catch it[.](#1.sentence-3)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
throw "Help!"; can be caught by a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ofconstchar* type:try {// ...} catch(const char* p) {// handle character string exceptions here} andclass Overflow {public: Overflow(char,double,double);};
|
||||
|
||||
void f(double x) {throw Overflow('+',x,3.45e107);} can be caught by a handler for exceptions of typeOverflow:try { f(1.2);} catch(Overflow& oo) {// handle exceptions of type Overflow here}
|
||||
|
||||
â *end example*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L244)
|
||||
|
||||
When an exception is thrown, control is transferred to the nearest handler with
|
||||
a matching type ([[except.handle]](except.handle "14.4 Handling an exception")); ânearestâ means the handler
|
||||
for which the[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") or[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]") following thetry keyword was most recently entered by the thread of control and not yet exited[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L257)
|
||||
|
||||
Throwing an exception
|
||||
initializes an object with dynamic storage duration,
|
||||
called the[*exception object*](#def:exception_handling,exception_object "14.2 Throwing an exception [except.throw]")[.](#3.sentence-1)
|
||||
|
||||
If the type of the exception object would be
|
||||
an incomplete type ([[basic.types.general]](basic.types.general "6.9.1 General")),
|
||||
an abstract class type ([[class.abstract]](class.abstract "11.7.4 Abstract classes")),
|
||||
or a pointer to an incomplete type other thancv void ([[basic.compound]](basic.compound "6.9.4 Compound types")),
|
||||
the program is ill-formed[.](#3.sentence-2)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L269)
|
||||
|
||||
The memory for the exception object is
|
||||
allocated in an unspecified way, except as noted in [[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")[.](#4.sentence-1)
|
||||
|
||||
If a handler exits by rethrowing, control is passed to another handler for
|
||||
the same exception object[.](#4.sentence-2)
|
||||
|
||||
The points of potential destruction for the exception object are:
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
when an active handler for the exception exits by
|
||||
any means other than
|
||||
rethrowing,
|
||||
immediately after the destruction of the object (if any)
|
||||
declared in the [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") in the handler;
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
when an object of type [std::exception_ptr](propagation#lib:exception_ptr "17.9.7 Exception propagation [propagation]") that refers to the exception object is destroyed,
|
||||
before the destructor of std::exception_ptr returns[.](#4.sentence-3)
|
||||
|
||||
Among all points of potential destruction for the exception object,
|
||||
there is an unspecified last one
|
||||
where the exception object is destroyed[.](#4.sentence-4)
|
||||
|
||||
All other points [happen before](intro.races#def:happens_before "6.10.2.2 Data races [intro.races]") that last one[.](#4.sentence-5)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
No other thread synchronization is implied in exception handling[.](#4.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
The implementation may then
|
||||
deallocate the memory for the exception object; any such deallocation
|
||||
is done in an unspecified way[.](#4.sentence-7)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
A thrown exception does not
|
||||
propagate to other threads unless caught, stored, and rethrown using
|
||||
appropriate library functions; see [[propagation]](propagation "17.9.7 Exception propagation") and [[futures]](futures "32.10 Futures")[.](#4.sentence-8)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L308)
|
||||
|
||||
Let T denote the type of the exception object[.](#5.sentence-1)
|
||||
|
||||
Copy-initialization of an object of type T from
|
||||
an lvalue of type const T in a context unrelated to T shall be well-formed[.](#5.sentence-2)
|
||||
|
||||
If T is a class type,
|
||||
the selected constructor is odr-used ([[basic.def.odr]](basic.def.odr "6.3 One-definition rule")) and
|
||||
the destructor of T is potentially invoked ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#5.sentence-3)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L319)
|
||||
|
||||
An exception is considered [*uncaught*](#def:uncaught_exception "14.2 Throwing an exception [except.throw]") after completing the initialization of the exception object
|
||||
until completing the activation of a handler for the exception ([[except.handle]](except.handle "14.4 Handling an exception"))[.](#6.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
As a consequence, an exception is considered uncaught
|
||||
during any stack unwinding resulting from it being thrown[.](#6.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L329)
|
||||
|
||||
If an exception is rethrown ([[expr.throw]](expr.throw "7.6.18 Throwing an exception"), [[propagation]](propagation "17.9.7 Exception propagation")),
|
||||
it is considered uncaught from the point of rethrow
|
||||
until the rethrown exception is caught[.](#7.sentence-1)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
The function std::uncaught_exceptions ([[uncaught.exceptions]](uncaught.exceptions "17.9.6 uncaught_exceptions"))
|
||||
returns the number of uncaught exceptions in the current thread[.](#7.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L339)
|
||||
|
||||
An exception is considered caught when a handler for that exception
|
||||
becomes [active](except.handle#def:exception_handling,handler,active "14.4 Handling an exception [except.handle]")[.](#8.sentence-1)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
An exception can have active handlers and still be considered uncaught if
|
||||
it is rethrown[.](#8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exceptions.tex#L349)
|
||||
|
||||
If the exception handling mechanism
|
||||
handling an uncaught exception
|
||||
directly invokes a function that exits via an
|
||||
exception, the function [std::terminate](except.terminate "14.6.2 The std::terminate function [except.terminate]") is invoked[.](#9.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*: struct C { C() { } C(const C&) {if (std::uncaught_exceptions()) {throw 0; // throw during copy to handler's [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") object ([[except.handle]](except.handle "14.4 Handling an exception"))}}};
|
||||
|
||||
int main() {try {throw C(); // calls std::terminate if construction of the handler's// [*exception-declaration*](except.pre#nt:exception-declaration "14.1 Preamble [except.pre]") object is not elided ([[class.copy.elision]](class.copy.elision "11.9.6 Copy/move elision"))} catch(C) { }} â *end example*]
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
If a destructor directly invoked by stack unwinding exits via an exception,std::terminate is invoked[.](#9.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
Reference in New Issue
Block a user