tmp/tmpmb215i_2/{from.md → to.md}
RENAMED
|
@@ -1,15 +1,14 @@
|
|
| 1 |
## Throwing an exception <a id="except.throw">[[except.throw]]</a>
|
| 2 |
|
| 3 |
Throwing an exception transfers control to a handler.
|
| 4 |
|
| 5 |
[*Note 1*: An exception can be thrown from one of the following
|
| 6 |
-
contexts: *throw-expression*s
|
| 7 |
-
[[basic.stc.dynamic.allocation]]
|
| 8 |
-
|
| 9 |
-
[[
|
| 10 |
-
[[structure.specifications]]). — *end note*]
|
| 11 |
|
| 12 |
An object is passed and the type of that object determines which
|
| 13 |
handlers can catch it.
|
| 14 |
|
| 15 |
[*Example 1*:
|
|
@@ -52,39 +51,39 @@ try {
|
|
| 52 |
```
|
| 53 |
|
| 54 |
— *end example*]
|
| 55 |
|
| 56 |
When an exception is thrown, control is transferred to the nearest
|
| 57 |
-
handler with a matching type
|
| 58 |
handler for which the *compound-statement* or *ctor-initializer*
|
| 59 |
following the `try` keyword was most recently entered by the thread of
|
| 60 |
control and not yet exited.
|
| 61 |
|
| 62 |
-
Throwing an exception copy-initializes ([[dcl.init]],
|
| 63 |
-
temporary object, called the *exception object*.
|
| 64 |
-
temporary is used to initialize the variable
|
| 65 |
-
*handler*
|
| 66 |
-
would be an incomplete type
|
| 67 |
-
|
|
|
|
| 68 |
|
| 69 |
The memory for the exception object is allocated in an unspecified way,
|
| 70 |
except as noted in [[basic.stc.dynamic.allocation]]. If a handler exits
|
| 71 |
by rethrowing, control is passed to another handler for the same
|
| 72 |
exception object. The points of potential destruction for the exception
|
| 73 |
object are:
|
| 74 |
|
| 75 |
- when an active handler for the exception exits by any means other than
|
| 76 |
rethrowing, immediately after the destruction of the object (if any)
|
| 77 |
declared in the *exception-declaration* in the handler;
|
| 78 |
-
- when an object of type `std::exception_ptr`
|
| 79 |
refers to the exception object is destroyed, before the destructor of
|
| 80 |
`std::exception_ptr` returns.
|
| 81 |
|
| 82 |
Among all points of potential destruction for the exception object,
|
| 83 |
there is an unspecified last one where the exception object is
|
| 84 |
-
destroyed. All other points happen before that last one
|
| 85 |
-
[[intro.races]]).
|
| 86 |
|
| 87 |
[*Note 2*: No other thread synchronization is implied in exception
|
| 88 |
handling. — *end note*]
|
| 89 |
|
| 90 |
The implementation may then deallocate the memory for the exception
|
|
@@ -95,44 +94,48 @@ unless caught, stored, and rethrown using appropriate library functions;
|
|
| 95 |
see [[propagation]] and [[futures]]. — *end note*]
|
| 96 |
|
| 97 |
When the thrown object is a class object, the constructor selected for
|
| 98 |
the copy-initialization as well as the constructor selected for a
|
| 99 |
copy-initialization considering the thrown object as an lvalue shall be
|
| 100 |
-
non-deleted and accessible, even if the copy/move operation is elided
|
| 101 |
-
[[class.copy]]
|
| 102 |
-
[[class.dtor]]
|
| 103 |
|
| 104 |
An exception is considered caught when a handler for that exception
|
| 105 |
-
becomes active
|
| 106 |
|
| 107 |
[*Note 4*: An exception can have active handlers and still be
|
| 108 |
considered uncaught if it is rethrown. — *end note*]
|
| 109 |
|
| 110 |
-
If the exception handling mechanism handling an uncaught exception
|
| 111 |
-
[[except.uncaught]]
|
| 112 |
-
exception, `std::terminate` is called
|
| 113 |
|
| 114 |
[*Example 2*:
|
| 115 |
|
| 116 |
``` cpp
|
| 117 |
struct C {
|
| 118 |
C() { }
|
| 119 |
C(const C&) {
|
| 120 |
if (std::uncaught_exceptions()) {
|
| 121 |
-
throw 0; // throw during copy to handler's exception-declaration object
|
| 122 |
}
|
| 123 |
}
|
| 124 |
};
|
| 125 |
|
| 126 |
int main() {
|
| 127 |
try {
|
| 128 |
-
throw C(); // calls std::terminate
|
| 129 |
-
// exception-declaration object is not elided
|
| 130 |
} catch(C) { }
|
| 131 |
}
|
| 132 |
```
|
| 133 |
|
| 134 |
— *end example*]
|
| 135 |
|
| 136 |
-
[*Note 5*:
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
|
|
|
| 1 |
## Throwing an exception <a id="except.throw">[[except.throw]]</a>
|
| 2 |
|
| 3 |
Throwing an exception transfers control to a handler.
|
| 4 |
|
| 5 |
[*Note 1*: An exception can be thrown from one of the following
|
| 6 |
+
contexts: *throw-expression*s [[expr.throw]], allocation functions
|
| 7 |
+
[[basic.stc.dynamic.allocation]], `dynamic_cast` [[expr.dynamic.cast]],
|
| 8 |
+
`typeid` [[expr.typeid]], *new-expression*s [[expr.new]], and standard
|
| 9 |
+
library functions [[structure.specifications]]. — *end note*]
|
|
|
|
| 10 |
|
| 11 |
An object is passed and the type of that object determines which
|
| 12 |
handlers can catch it.
|
| 13 |
|
| 14 |
[*Example 1*:
|
|
|
|
| 51 |
```
|
| 52 |
|
| 53 |
— *end example*]
|
| 54 |
|
| 55 |
When an exception is thrown, control is transferred to the nearest
|
| 56 |
+
handler with a matching type [[except.handle]]; “nearest” means the
|
| 57 |
handler for which the *compound-statement* or *ctor-initializer*
|
| 58 |
following the `try` keyword was most recently entered by the thread of
|
| 59 |
control and not yet exited.
|
| 60 |
|
| 61 |
+
Throwing an exception copy-initializes ([[dcl.init]],
|
| 62 |
+
[[class.copy.ctor]]) a temporary object, called the *exception object*.
|
| 63 |
+
An lvalue denoting the temporary is used to initialize the variable
|
| 64 |
+
declared in the matching *handler* [[except.handle]]. If the type of the
|
| 65 |
+
exception object would be an incomplete type, an abstract class type
|
| 66 |
+
[[class.abstract]], or a pointer to an incomplete type other than
|
| 67 |
+
cv `void` the program is ill-formed.
|
| 68 |
|
| 69 |
The memory for the exception object is allocated in an unspecified way,
|
| 70 |
except as noted in [[basic.stc.dynamic.allocation]]. If a handler exits
|
| 71 |
by rethrowing, control is passed to another handler for the same
|
| 72 |
exception object. The points of potential destruction for the exception
|
| 73 |
object are:
|
| 74 |
|
| 75 |
- when an active handler for the exception exits by any means other than
|
| 76 |
rethrowing, immediately after the destruction of the object (if any)
|
| 77 |
declared in the *exception-declaration* in the handler;
|
| 78 |
+
- when an object of type `std::exception_ptr` [[propagation]] that
|
| 79 |
refers to the exception object is destroyed, before the destructor of
|
| 80 |
`std::exception_ptr` returns.
|
| 81 |
|
| 82 |
Among all points of potential destruction for the exception object,
|
| 83 |
there is an unspecified last one where the exception object is
|
| 84 |
+
destroyed. All other points happen before that last one [[intro.races]].
|
|
|
|
| 85 |
|
| 86 |
[*Note 2*: No other thread synchronization is implied in exception
|
| 87 |
handling. — *end note*]
|
| 88 |
|
| 89 |
The implementation may then deallocate the memory for the exception
|
|
|
|
| 94 |
see [[propagation]] and [[futures]]. — *end note*]
|
| 95 |
|
| 96 |
When the thrown object is a class object, the constructor selected for
|
| 97 |
the copy-initialization as well as the constructor selected for a
|
| 98 |
copy-initialization considering the thrown object as an lvalue shall be
|
| 99 |
+
non-deleted and accessible, even if the copy/move operation is elided
|
| 100 |
+
[[class.copy.elision]]. The destructor is potentially invoked
|
| 101 |
+
[[class.dtor]].
|
| 102 |
|
| 103 |
An exception is considered caught when a handler for that exception
|
| 104 |
+
becomes active [[except.handle]].
|
| 105 |
|
| 106 |
[*Note 4*: An exception can have active handlers and still be
|
| 107 |
considered uncaught if it is rethrown. — *end note*]
|
| 108 |
|
| 109 |
+
If the exception handling mechanism handling an uncaught exception
|
| 110 |
+
[[except.uncaught]] directly invokes a function that exits via an
|
| 111 |
+
exception, the function `std::terminate` is called [[except.terminate]].
|
| 112 |
|
| 113 |
[*Example 2*:
|
| 114 |
|
| 115 |
``` cpp
|
| 116 |
struct C {
|
| 117 |
C() { }
|
| 118 |
C(const C&) {
|
| 119 |
if (std::uncaught_exceptions()) {
|
| 120 |
+
throw 0; // throw during copy to handler's exception-declaration object[except.handle]
|
| 121 |
}
|
| 122 |
}
|
| 123 |
};
|
| 124 |
|
| 125 |
int main() {
|
| 126 |
try {
|
| 127 |
+
throw C(); // calls std::terminate if construction of the handler's
|
| 128 |
+
// exception-declaration object is not elided[class.copy.elision]
|
| 129 |
} catch(C) { }
|
| 130 |
}
|
| 131 |
```
|
| 132 |
|
| 133 |
— *end example*]
|
| 134 |
|
| 135 |
+
[*Note 5*:
|
| 136 |
+
|
| 137 |
+
Consequently, destructors should generally catch exceptions and not let
|
| 138 |
+
them propagate.
|
| 139 |
+
|
| 140 |
+
— *end note*]
|
| 141 |
|