tmp/tmpio5qyobj/{from.md → to.md}
RENAMED
|
@@ -1,26 +1,31 @@
|
|
| 1 |
## Throwing an exception <a id="except.throw">[[except.throw]]</a>
|
| 2 |
|
| 3 |
-
Throwing an exception transfers control to a handler.
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
[[
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
``` cpp
|
| 12 |
throw "Help!";
|
| 13 |
```
|
| 14 |
|
| 15 |
can be caught by a *handler* of `const` `char*` type:
|
| 16 |
|
| 17 |
``` cpp
|
| 18 |
try {
|
| 19 |
// ...
|
| 20 |
-
}
|
| 21 |
-
catch(const char* p) {
|
| 22 |
// handle character string exceptions here
|
| 23 |
}
|
| 24 |
```
|
| 25 |
|
| 26 |
and
|
|
@@ -34,73 +39,87 @@ public:
|
|
| 34 |
void f(double x) {
|
| 35 |
throw Overflow('+',x,3.45e107);
|
| 36 |
}
|
| 37 |
```
|
| 38 |
|
| 39 |
-
can be caught by a handler for exceptions of type `Overflow`
|
| 40 |
|
| 41 |
``` cpp
|
| 42 |
try {
|
| 43 |
f(1.2);
|
| 44 |
} catch(Overflow& oo) {
|
| 45 |
// handle exceptions of type Overflow here
|
| 46 |
}
|
| 47 |
```
|
| 48 |
|
|
|
|
|
|
|
| 49 |
When an exception is thrown, control is transferred to the nearest
|
| 50 |
handler with a matching type ([[except.handle]]); “nearest” means the
|
| 51 |
handler for which the *compound-statement* or *ctor-initializer*
|
| 52 |
following the `try` keyword was most recently entered by the thread of
|
| 53 |
control and not yet exited.
|
| 54 |
|
| 55 |
Throwing an exception copy-initializes ([[dcl.init]], [[class.copy]]) a
|
| 56 |
-
temporary object, called the *exception object*.
|
| 57 |
-
|
| 58 |
*handler* ([[except.handle]]). If the type of the exception object
|
| 59 |
would be an incomplete type or a pointer to an incomplete type other
|
| 60 |
-
than
|
| 61 |
-
Evaluating a *throw-expression* with an operand throws an exception; the
|
| 62 |
-
type of the exception object is determined by removing any top-level
|
| 63 |
-
*cv-qualifiers* from the static type of the operand and adjusting the
|
| 64 |
-
type from “array of `T`” or “function returning `T`” to “pointer to `T`”
|
| 65 |
-
or “pointer to function returning `T`,” respectively.
|
| 66 |
|
| 67 |
The memory for the exception object is allocated in an unspecified way,
|
| 68 |
except as noted in [[basic.stc.dynamic.allocation]]. If a handler exits
|
| 69 |
by rethrowing, control is passed to another handler for the same
|
| 70 |
-
exception. The
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
`std::exception_ptr` returns.
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
unless caught, stored, and rethrown using appropriate library functions;
|
| 82 |
-
see [[propagation]] and [[futures]].
|
| 83 |
|
| 84 |
When the thrown object is a class object, the constructor selected for
|
| 85 |
-
the copy-initialization
|
| 86 |
-
the
|
|
|
|
|
|
|
|
|
|
| 87 |
|
| 88 |
An exception is considered caught when a handler for that exception
|
| 89 |
-
becomes active ([[except.handle]]).
|
| 90 |
-
handlers and still be considered uncaught if it is rethrown.
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
``` cpp
|
| 98 |
struct C {
|
| 99 |
C() { }
|
| 100 |
C(const C&) {
|
| 101 |
-
if (std::
|
| 102 |
throw 0; // throw during copy to handler's exception-declaration object~([except.handle])
|
| 103 |
}
|
| 104 |
}
|
| 105 |
};
|
| 106 |
|
|
@@ -110,27 +129,10 @@ int main() {
|
|
| 110 |
// exception-declaration object is not elided~([class.copy])
|
| 111 |
} catch(C) { }
|
| 112 |
}
|
| 113 |
```
|
| 114 |
|
| 115 |
-
|
| 116 |
-
exception ([[except.handle]]). The exception is reactivated with the
|
| 117 |
-
existing exception object; no new exception object is created. The
|
| 118 |
-
exception is no longer considered to be caught; therefore, the value of
|
| 119 |
-
`std::uncaught_exception()` will again be `true`. code that must be
|
| 120 |
-
executed because of an exception yet cannot completely handle the
|
| 121 |
-
exception can be written like this:
|
| 122 |
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
// ...
|
| 126 |
-
} catch (...) { // catch all exceptions
|
| 127 |
-
// respond (partially) to exception
|
| 128 |
-
throw; // pass the exception to some
|
| 129 |
-
// other handler
|
| 130 |
-
}
|
| 131 |
-
```
|
| 132 |
-
|
| 133 |
-
If no exception is presently being handled, executing a
|
| 134 |
-
*throw-expression* with no operand calls `std::terminate()` (
|
| 135 |
-
[[except.terminate]]).
|
| 136 |
|
|
|
|
| 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` (
|
| 8 |
+
[[expr.dynamic.cast]]), `typeid` ([[expr.typeid]]), *new-expression*s (
|
| 9 |
+
[[expr.new]]), and standard library functions (
|
| 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*:
|
| 16 |
|
| 17 |
``` cpp
|
| 18 |
throw "Help!";
|
| 19 |
```
|
| 20 |
|
| 21 |
can be caught by a *handler* of `const` `char*` type:
|
| 22 |
|
| 23 |
``` cpp
|
| 24 |
try {
|
| 25 |
// ...
|
| 26 |
+
} catch(const char* p) {
|
|
|
|
| 27 |
// handle character string exceptions here
|
| 28 |
}
|
| 29 |
```
|
| 30 |
|
| 31 |
and
|
|
|
|
| 39 |
void f(double x) {
|
| 40 |
throw Overflow('+',x,3.45e107);
|
| 41 |
}
|
| 42 |
```
|
| 43 |
|
| 44 |
+
can be caught by a handler for exceptions of type `Overflow`:
|
| 45 |
|
| 46 |
``` cpp
|
| 47 |
try {
|
| 48 |
f(1.2);
|
| 49 |
} catch(Overflow& oo) {
|
| 50 |
// handle exceptions of type Overflow here
|
| 51 |
}
|
| 52 |
```
|
| 53 |
|
| 54 |
+
— *end example*]
|
| 55 |
+
|
| 56 |
When an exception is thrown, control is transferred to the nearest
|
| 57 |
handler with a matching type ([[except.handle]]); “nearest” means the
|
| 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]], [[class.copy]]) a
|
| 63 |
+
temporary object, called the *exception object*. An lvalue denoting the
|
| 64 |
+
temporary is used to initialize the variable declared in the matching
|
| 65 |
*handler* ([[except.handle]]). If the type of the exception object
|
| 66 |
would be an incomplete type or a pointer to an incomplete type other
|
| 67 |
+
than 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 (
|
| 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
|
| 91 |
+
object; any such deallocation is done in an unspecified way.
|
| 92 |
+
|
| 93 |
+
[*Note 3*: A thrown exception does not propagate to other threads
|
| 94 |
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]]). The destructor is potentially invoked (
|
| 102 |
+
[[class.dtor]]).
|
| 103 |
|
| 104 |
An exception is considered caught when a handler for that exception
|
| 105 |
+
becomes active ([[except.handle]]).
|
|
|
|
| 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]]) directly invokes a function that exits via an
|
| 112 |
+
exception, `std::terminate` is called ([[except.terminate]]).
|
| 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~([except.handle])
|
| 122 |
}
|
| 123 |
}
|
| 124 |
};
|
| 125 |
|
|
|
|
| 129 |
// exception-declaration object is not elided~([class.copy])
|
| 130 |
} catch(C) { }
|
| 131 |
}
|
| 132 |
```
|
| 133 |
|
| 134 |
+
— *end example*]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
|
| 136 |
+
[*Note 5*: Consequently, destructors should generally catch exceptions
|
| 137 |
+
and not let them propagate. — *end note*]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|