- tmp/tmp_l39h7hi/{from.md → to.md} +399 -440
tmp/tmp_l39h7hi/{from.md → to.md}
RENAMED
|
@@ -32,46 +32,48 @@ exception-declaration:
|
|
| 32 |
attribute-specifier-seqₒₚₜ type-specifier-seq declarator
|
| 33 |
attribute-specifier-seqₒₚₜ type-specifier-seq abstract-declaratorₒₚₜ
|
| 34 |
'...'
|
| 35 |
```
|
| 36 |
|
| 37 |
-
``` bnf
|
| 38 |
-
throw-expression:
|
| 39 |
-
'throw' assignment-expressionₒₚₜ
|
| 40 |
-
```
|
| 41 |
-
|
| 42 |
The optional *attribute-specifier-seq* in an *exception-declaration*
|
| 43 |
appertains to the parameter of the catch clause ([[except.handle]]).
|
| 44 |
|
| 45 |
-
A *try-block* is a *statement* (Clause [[stmt.stmt]]).
|
| 46 |
-
|
| 47 |
-
|
|
|
|
| 48 |
|
| 49 |
A `goto` or `switch` statement shall not be used to transfer control
|
| 50 |
into a try block or into a handler.
|
| 51 |
|
|
|
|
|
|
|
| 52 |
``` cpp
|
| 53 |
void f() {
|
| 54 |
-
goto l1; //
|
| 55 |
-
goto l2; //
|
| 56 |
try {
|
| 57 |
goto l1; // OK
|
| 58 |
-
goto l2; //
|
| 59 |
l1: ;
|
| 60 |
} catch (...) {
|
| 61 |
l2: ;
|
| 62 |
-
goto l1; //
|
| 63 |
goto l2; // OK
|
| 64 |
}
|
| 65 |
}
|
| 66 |
```
|
| 67 |
|
|
|
|
|
|
|
| 68 |
A `goto`, `break`, `return`, or `continue` statement can be used to
|
| 69 |
transfer control out of a try block or handler. When this happens, each
|
| 70 |
variable declared in the try block will be destroyed in the context that
|
| 71 |
directly contains its declaration.
|
| 72 |
|
|
|
|
|
|
|
| 73 |
``` cpp
|
| 74 |
lab: try {
|
| 75 |
T1 t1;
|
| 76 |
try {
|
| 77 |
T2 t2;
|
|
@@ -80,23 +82,27 @@ lab: try {
|
|
| 80 |
} catch(...) { /* handler 2 */ }
|
| 81 |
} catch(...) { /* handler 1 */ }
|
| 82 |
```
|
| 83 |
|
| 84 |
Here, executing `goto lab;` will destroy first `t2`, then `t1`, assuming
|
| 85 |
-
the *condition* does not declare a variable. Any exception
|
| 86 |
-
destroying `t2` will result in executing
|
| 87 |
-
|
|
|
|
|
|
|
| 88 |
|
| 89 |
A *function-try-block* associates a *handler-seq* with the
|
| 90 |
*ctor-initializer*, if present, and the *compound-statement*. An
|
| 91 |
exception thrown during the execution of the *compound-statement* or,
|
| 92 |
for constructors and destructors, during the initialization or
|
| 93 |
destruction, respectively, of the class’s subobjects, transfers control
|
| 94 |
to a handler in a *function-try-block* in the same way as an exception
|
| 95 |
thrown during the execution of a *try-block* transfers control to other
|
| 96 |
handlers.
|
| 97 |
|
|
|
|
|
|
|
| 98 |
``` cpp
|
| 99 |
int f(int);
|
| 100 |
class C {
|
| 101 |
int i;
|
| 102 |
double d;
|
|
@@ -105,38 +111,46 @@ public:
|
|
| 105 |
};
|
| 106 |
|
| 107 |
C::C(int ii, double id)
|
| 108 |
try : i(f(ii)), d(id) {
|
| 109 |
// constructor statements
|
| 110 |
-
}
|
| 111 |
-
|
| 112 |
-
// handles exceptions thrown from the ctor-initializer
|
| 113 |
-
// and from the constructor statements
|
| 114 |
}
|
| 115 |
```
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
## Throwing an exception <a id="except.throw">[[except.throw]]</a>
|
| 118 |
|
| 119 |
-
Throwing an exception transfers control to a handler.
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
[[
|
| 125 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
|
| 127 |
``` cpp
|
| 128 |
throw "Help!";
|
| 129 |
```
|
| 130 |
|
| 131 |
can be caught by a *handler* of `const` `char*` type:
|
| 132 |
|
| 133 |
``` cpp
|
| 134 |
try {
|
| 135 |
// ...
|
| 136 |
-
}
|
| 137 |
-
catch(const char* p) {
|
| 138 |
// handle character string exceptions here
|
| 139 |
}
|
| 140 |
```
|
| 141 |
|
| 142 |
and
|
|
@@ -150,73 +164,87 @@ public:
|
|
| 150 |
void f(double x) {
|
| 151 |
throw Overflow('+',x,3.45e107);
|
| 152 |
}
|
| 153 |
```
|
| 154 |
|
| 155 |
-
can be caught by a handler for exceptions of type `Overflow`
|
| 156 |
|
| 157 |
``` cpp
|
| 158 |
try {
|
| 159 |
f(1.2);
|
| 160 |
} catch(Overflow& oo) {
|
| 161 |
// handle exceptions of type Overflow here
|
| 162 |
}
|
| 163 |
```
|
| 164 |
|
|
|
|
|
|
|
| 165 |
When an exception is thrown, control is transferred to the nearest
|
| 166 |
handler with a matching type ([[except.handle]]); “nearest” means the
|
| 167 |
handler for which the *compound-statement* or *ctor-initializer*
|
| 168 |
following the `try` keyword was most recently entered by the thread of
|
| 169 |
control and not yet exited.
|
| 170 |
|
| 171 |
Throwing an exception copy-initializes ([[dcl.init]], [[class.copy]]) a
|
| 172 |
-
temporary object, called the *exception object*.
|
| 173 |
-
|
| 174 |
*handler* ([[except.handle]]). If the type of the exception object
|
| 175 |
would be an incomplete type or a pointer to an incomplete type other
|
| 176 |
-
than
|
| 177 |
-
Evaluating a *throw-expression* with an operand throws an exception; the
|
| 178 |
-
type of the exception object is determined by removing any top-level
|
| 179 |
-
*cv-qualifiers* from the static type of the operand and adjusting the
|
| 180 |
-
type from “array of `T`” or “function returning `T`” to “pointer to `T`”
|
| 181 |
-
or “pointer to function returning `T`,” respectively.
|
| 182 |
|
| 183 |
The memory for the exception object is allocated in an unspecified way,
|
| 184 |
except as noted in [[basic.stc.dynamic.allocation]]. If a handler exits
|
| 185 |
by rethrowing, control is passed to another handler for the same
|
| 186 |
-
exception. The
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
`std::exception_ptr` returns.
|
| 195 |
-
|
| 196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
unless caught, stored, and rethrown using appropriate library functions;
|
| 198 |
-
see [[propagation]] and [[futures]].
|
| 199 |
|
| 200 |
When the thrown object is a class object, the constructor selected for
|
| 201 |
-
the copy-initialization
|
| 202 |
-
the
|
|
|
|
|
|
|
|
|
|
| 203 |
|
| 204 |
An exception is considered caught when a handler for that exception
|
| 205 |
-
becomes active ([[except.handle]]).
|
| 206 |
-
handlers and still be considered uncaught if it is rethrown.
|
| 207 |
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
|
| 213 |
``` cpp
|
| 214 |
struct C {
|
| 215 |
C() { }
|
| 216 |
C(const C&) {
|
| 217 |
-
if (std::
|
| 218 |
throw 0; // throw during copy to handler's exception-declaration object~([except.handle])
|
| 219 |
}
|
| 220 |
}
|
| 221 |
};
|
| 222 |
|
|
@@ -226,58 +254,76 @@ int main() {
|
|
| 226 |
// exception-declaration object is not elided~([class.copy])
|
| 227 |
} catch(C) { }
|
| 228 |
}
|
| 229 |
```
|
| 230 |
|
| 231 |
-
|
| 232 |
-
exception ([[except.handle]]). The exception is reactivated with the
|
| 233 |
-
existing exception object; no new exception object is created. The
|
| 234 |
-
exception is no longer considered to be caught; therefore, the value of
|
| 235 |
-
`std::uncaught_exception()` will again be `true`. code that must be
|
| 236 |
-
executed because of an exception yet cannot completely handle the
|
| 237 |
-
exception can be written like this:
|
| 238 |
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
// ...
|
| 242 |
-
} catch (...) { // catch all exceptions
|
| 243 |
-
// respond (partially) to exception
|
| 244 |
-
throw; // pass the exception to some
|
| 245 |
-
// other handler
|
| 246 |
-
}
|
| 247 |
-
```
|
| 248 |
-
|
| 249 |
-
If no exception is presently being handled, executing a
|
| 250 |
-
*throw-expression* with no operand calls `std::terminate()` (
|
| 251 |
-
[[except.terminate]]).
|
| 252 |
|
| 253 |
## Constructors and destructors <a id="except.ctor">[[except.ctor]]</a>
|
| 254 |
|
| 255 |
As control passes from the point where an exception is thrown to a
|
| 256 |
-
handler, destructors are invoked
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
|
| 280 |
## Handling an exception <a id="except.handle">[[except.handle]]</a>
|
| 281 |
|
| 282 |
The *exception-declaration* in a *handler* describes the type(s) of
|
| 283 |
exceptions that can cause that *handler* to be entered. The
|
|
@@ -285,37 +331,41 @@ exceptions that can cause that *handler* to be entered. The
|
|
| 285 |
class type, or an rvalue reference type. The *exception-declaration*
|
| 286 |
shall not denote a pointer or reference to an incomplete type, other
|
| 287 |
than `void*`, `const` `void*`, `volatile` `void*`, or `const` `volatile`
|
| 288 |
`void*`.
|
| 289 |
|
| 290 |
-
A handler of type “array of `T`” or
|
| 291 |
-
|
| 292 |
-
respectively.
|
| 293 |
|
| 294 |
A *handler* is a match for an exception object of type `E` if
|
| 295 |
|
| 296 |
-
- The *handler* is of type
|
| 297 |
-
same type (ignoring the top-level *cv-
|
| 298 |
-
- the *handler* is of type
|
| 299 |
-
|
| 300 |
-
- the *handler* is of type
|
| 301 |
-
type and `E` is a pointer
|
| 302 |
-
or
|
| 303 |
- a standard pointer conversion ([[conv.ptr]]) not involving
|
| 304 |
conversions to pointers to private or protected or ambiguous classes
|
| 305 |
-
- a
|
| 306 |
-
-
|
|
|
|
| 307 |
or pointer to member type and `E` is `std::nullptr_t`.
|
| 308 |
|
| 309 |
-
A *throw-expression* whose operand is an integer literal
|
| 310 |
-
does not match a handler of pointer or pointer to member
|
|
|
|
|
|
|
|
|
|
|
|
|
| 311 |
|
| 312 |
``` cpp
|
| 313 |
-
class Matherr {
|
| 314 |
-
class Overflow: public Matherr {
|
| 315 |
-
class Underflow: public Matherr {
|
| 316 |
-
class Zerodivide: public Matherr {
|
| 317 |
|
| 318 |
void f() {
|
| 319 |
try {
|
| 320 |
g();
|
| 321 |
} catch (Overflow oo) {
|
|
@@ -329,14 +379,18 @@ void f() {
|
|
| 329 |
Here, the `Overflow` handler will catch exceptions of type `Overflow`
|
| 330 |
and the `Matherr` handler will catch exceptions of type `Matherr` and of
|
| 331 |
all types publicly derived from `Matherr` including exceptions of type
|
| 332 |
`Underflow` and `Zerodivide`.
|
| 333 |
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
|
| 339 |
A `...` in a handler’s *exception-declaration* functions similarly to
|
| 340 |
`...` in a function parameter declaration; it specifies a match for any
|
| 341 |
exception. If present, a `...` handler shall be the last handler for its
|
| 342 |
try block.
|
|
@@ -344,15 +398,18 @@ try block.
|
|
| 344 |
If no match is found among the handlers for a try block, the search for
|
| 345 |
a matching handler continues in a dynamically surrounding try block of
|
| 346 |
the same thread.
|
| 347 |
|
| 348 |
A handler is considered active when initialization is complete for the
|
| 349 |
-
parameter (if any) of the catch clause.
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
|
|
|
|
|
|
|
|
|
| 354 |
|
| 355 |
The exception with the most recently activated handler that is still
|
| 356 |
active is called the *currently handled exception*.
|
| 357 |
|
| 358 |
If no matching handler is found, the function `std::terminate()` is
|
|
@@ -361,44 +418,32 @@ called; whether or not the stack is unwound before this call to
|
|
| 361 |
|
| 362 |
Referring to any non-static member or base class of an object in the
|
| 363 |
handler for a *function-try-block* of a constructor or destructor for
|
| 364 |
that object results in undefined behavior.
|
| 365 |
|
| 366 |
-
The fully constructed base classes and members of an object shall be
|
| 367 |
-
destroyed before entering the handler of a *function-try-block* of a
|
| 368 |
-
constructor for that object. Similarly, if a delegating constructor for
|
| 369 |
-
an object exits with an exception after the non-delegating constructor
|
| 370 |
-
for that object has completed execution, the object’s destructor shall
|
| 371 |
-
be executed before entering the handler of a of a constructor for that
|
| 372 |
-
object. The base classes and non-variant members of an object shall be
|
| 373 |
-
destroyed before entering the handler of a of a destructor for that
|
| 374 |
-
object ([[class.dtor]]).
|
| 375 |
-
|
| 376 |
The scope and lifetime of the parameters of a function or constructor
|
| 377 |
extend into the handlers of a *function-try-block*.
|
| 378 |
|
| 379 |
Exceptions thrown in destructors of objects with static storage duration
|
| 380 |
or in constructors of namespace-scope objects with static storage
|
| 381 |
-
duration are not caught by a *function-try-block* on `main
|
| 382 |
-
Exceptions thrown in destructors of
|
| 383 |
-
|
| 384 |
-
duration are not caught by a
|
| 385 |
-
function of the thread.
|
| 386 |
|
| 387 |
If a return statement appears in a handler of the *function-try-block*
|
| 388 |
of a constructor, the program is ill-formed.
|
| 389 |
|
| 390 |
The currently handled exception is rethrown if control reaches the end
|
| 391 |
of a handler of the *function-try-block* of a constructor or destructor.
|
| 392 |
-
Otherwise,
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
results in undefined behavior in a value-returning function (
|
| 396 |
-
[[stmt.return]]).
|
| 397 |
|
| 398 |
-
The variable declared by the *exception-declaration*, of type cv
|
| 399 |
-
cv
|
| 400 |
follows:
|
| 401 |
|
| 402 |
- if `T` is a base class of `E`, the variable is copy-initialized (
|
| 403 |
[[dcl.init]]) from the corresponding base class subobject of the
|
| 404 |
exception object;
|
|
@@ -413,428 +458,342 @@ affect the exception object. When the handler declares a reference to an
|
|
| 413 |
object, any changes to the referenced object are changes to the
|
| 414 |
exception object and will have effect should that object be rethrown.
|
| 415 |
|
| 416 |
## Exception specifications <a id="except.spec">[[except.spec]]</a>
|
| 417 |
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
|
| 422 |
``` bnf
|
| 423 |
-
|
| 424 |
-
dynamic-exception-specification
|
| 425 |
-
noexcept-specification
|
| 426 |
-
```
|
| 427 |
-
|
| 428 |
-
``` bnf
|
| 429 |
-
dynamic-exception-specification:
|
| 430 |
-
'throw (' type-id-listₒₚₜ ')'
|
| 431 |
-
```
|
| 432 |
-
|
| 433 |
-
``` bnf
|
| 434 |
-
type-id-list:
|
| 435 |
-
type-id '...'ₒₚₜ
|
| 436 |
-
type-id-list ',' type-id '...'ₒₚₜ
|
| 437 |
-
```
|
| 438 |
-
|
| 439 |
-
``` bnf
|
| 440 |
-
noexcept-specification:
|
| 441 |
'noexcept' '(' constant-expression ')'
|
| 442 |
'noexcept'
|
|
|
|
| 443 |
```
|
| 444 |
|
| 445 |
-
In a *noexcept-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
`noexcept` is part of the *noexcept-
|
| 450 |
-
an initializer ([[dcl.init]]).
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
| 468 |
-
|
| 469 |
-
|
| 470 |
-
or “function returning `T`” denoted in an *exception-specification* is
|
| 471 |
-
adjusted to type `T`, “pointer to `T`”, or “pointer to function
|
| 472 |
-
returning `T`”, respectively.
|
| 473 |
-
|
| 474 |
-
Two *exception-specification*s are *compatible* if:
|
| 475 |
-
|
| 476 |
-
- both are non-throwing (see below), regardless of their form,
|
| 477 |
-
- both have the form `noexcept(`*constant-expression*`)` and the
|
| 478 |
-
*constant-expression*s are equivalent, or
|
| 479 |
-
- both are *dynamic-exception-specification*s that have the same set of
|
| 480 |
-
adjusted types.
|
| 481 |
-
|
| 482 |
-
If any declaration of a function has an *exception-specification* that
|
| 483 |
-
is not a *noexcept-specification* allowing all exceptions, all
|
| 484 |
-
declarations, including the definition and any explicit specialization,
|
| 485 |
-
of that function shall have a compatible *exception-specification*. If
|
| 486 |
-
any declaration of a pointer to function, reference to function, or
|
| 487 |
-
pointer to member function has an *exception-specification*, all
|
| 488 |
-
occurrences of that declaration shall have a compatible
|
| 489 |
-
*exception-specification* In an explicit instantiation an
|
| 490 |
-
*exception-specification* may be specified, but is not required. If an
|
| 491 |
-
*exception-specification* is specified in an explicit instantiation
|
| 492 |
-
directive, it shall be compatible with the *exception-specification*s of
|
| 493 |
-
other declarations of that function. A diagnostic is required only if
|
| 494 |
-
the *exception-specification*s are not compatible within a single
|
| 495 |
-
translation unit.
|
| 496 |
-
|
| 497 |
-
If a virtual function has an *exception-specification*, all
|
| 498 |
declarations, including the definition, of any function that overrides
|
| 499 |
-
that virtual function in any derived class shall
|
| 500 |
-
|
| 501 |
-
|
|
|
|
|
|
|
| 502 |
|
| 503 |
``` cpp
|
| 504 |
struct B {
|
| 505 |
-
virtual void f()
|
| 506 |
virtual void g();
|
|
|
|
| 507 |
};
|
| 508 |
|
| 509 |
struct D: B {
|
| 510 |
void f(); // ill-formed
|
| 511 |
-
void g()
|
|
|
|
| 512 |
};
|
| 513 |
```
|
| 514 |
|
| 515 |
-
The declaration of `D::f` is ill-formed because it
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
functions, pointers to member functions, and references to functions:
|
| 519 |
-
the target entity shall allow at least the exceptions allowed by the
|
| 520 |
-
source value in the assignment or initialization.
|
| 521 |
|
| 522 |
-
|
| 523 |
-
class A { /* ... */ };
|
| 524 |
-
void (*pf1)(); // no exception specification
|
| 525 |
-
void (*pf2)() throw(A);
|
| 526 |
-
|
| 527 |
-
void f() {
|
| 528 |
-
pf1 = pf2; // OK: pf1 is less restrictive
|
| 529 |
-
pf2 = pf1; // error: pf2 is more restrictive
|
| 530 |
-
}
|
| 531 |
-
```
|
| 532 |
-
|
| 533 |
-
In such an assignment or initialization, *exception-specification*s on
|
| 534 |
-
return types and parameter types shall be compatible. In other
|
| 535 |
-
assignments or initializations, *exception-specification*s shall be
|
| 536 |
-
compatible.
|
| 537 |
-
|
| 538 |
-
An *exception-specification* can include the same type more than once
|
| 539 |
-
and can include classes that are related by inheritance, even though
|
| 540 |
-
doing so is redundant. An *exception-specification* can also include the
|
| 541 |
-
class `std::bad_exception` ([[bad.exception]]).
|
| 542 |
-
|
| 543 |
-
A function is said to *allow* an exception of type `E` if the
|
| 544 |
-
*constant-expression* in its *noexcept-specification* evaluates to
|
| 545 |
-
`false` or its *dynamic-exception-specification* contains a type `T` for
|
| 546 |
-
which a handler of type `T` would be a match ([[except.handle]]) for an
|
| 547 |
-
exception of type `E`.
|
| 548 |
|
| 549 |
Whenever an exception is thrown and the search for a handler (
|
| 550 |
-
[[except.handle]]) encounters the outermost block of a function with
|
| 551 |
-
|
|
|
|
| 552 |
|
| 553 |
-
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
|
| 559 |
``` cpp
|
| 560 |
-
|
| 561 |
-
class Y { };
|
| 562 |
-
class Z: public X { };
|
| 563 |
-
class W { };
|
| 564 |
|
| 565 |
-
void
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
if (n) throw Z(); // also OK
|
| 569 |
-
throw W(); // will call std::unexpected()
|
| 570 |
}
|
| 571 |
```
|
| 572 |
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
definition is used.
|
| 576 |
|
| 577 |
-
|
| 578 |
-
*exception-specification* for which it was invoked, and in this case the
|
| 579 |
-
search for another handler will continue at the call of the function
|
| 580 |
-
with this *exception-specification* (see [[except.unexpected]]), or it
|
| 581 |
-
may call `std::terminate()`.
|
| 582 |
|
| 583 |
-
An
|
| 584 |
-
executed it throws or might throw an exception that the containing
|
| 585 |
-
function does not allow.
|
| 586 |
|
| 587 |
-
``
|
| 588 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 589 |
|
| 590 |
-
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 594 |
|
| 595 |
-
|
| 596 |
-
|
|
|
|
|
|
|
| 597 |
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
|
| 602 |
-
|
| 603 |
-
`noexcept(`*constant-expression*`)` where the *constant-expression*
|
| 604 |
-
yields `true`. A function with a non-throwing *exception-specification*
|
| 605 |
-
does not allow any exceptions.
|
| 606 |
|
| 607 |
-
|
| 608 |
-
|
|
|
|
| 609 |
|
| 610 |
-
|
| 611 |
-
declared special member function (Clause [[special]]) have an
|
| 612 |
-
*exception-specification*. If `f` is an inheriting constructor or an
|
| 613 |
-
implicitly declared default constructor, copy constructor, move
|
| 614 |
-
constructor, destructor, copy assignment operator, or move assignment
|
| 615 |
-
operator, its implicit *exception-specification* specifies the *type-id*
|
| 616 |
-
`T` if and only if `T` is allowed by the *exception-specification* of a
|
| 617 |
-
function directly invoked by `f`’s implicit definition; `f` allows all
|
| 618 |
-
exceptions if any function it directly invokes allows all exceptions,
|
| 619 |
-
and `f` has the *exception-specification* `noexcept(true)` if every
|
| 620 |
-
function it directly invokes allows no exceptions. It follows that `f`
|
| 621 |
-
has the *exception-specification* `noexcept(true)` if it invokes no
|
| 622 |
-
other functions. An instantiation of an inheriting constructor template
|
| 623 |
-
has an implied *exception-specification* as if it were a non-template
|
| 624 |
-
inheriting constructor.
|
| 625 |
|
| 626 |
``` cpp
|
| 627 |
struct A {
|
| 628 |
-
A();
|
| 629 |
-
A(const A&)
|
| 630 |
-
A(A&&)
|
| 631 |
-
~A()
|
| 632 |
};
|
| 633 |
struct B {
|
| 634 |
B() throw();
|
| 635 |
-
B(const B&) = default;
|
| 636 |
-
B(B&&
|
| 637 |
-
~B()
|
| 638 |
};
|
|
|
|
| 639 |
struct D : public A, public B {
|
| 640 |
-
|
| 641 |
-
//
|
| 642 |
-
//
|
| 643 |
-
//
|
|
|
|
| 644 |
};
|
| 645 |
```
|
| 646 |
|
| 647 |
-
Furthermore, if `A::~A()`
|
| 648 |
-
|
| 649 |
-
|
| 650 |
-
base class
|
| 651 |
-
restrictive as that in the base class.
|
| 652 |
|
| 653 |
-
|
| 654 |
-
explicit *exception-specification* is treated as if it were specified
|
| 655 |
-
with `noexcept(true)`.
|
| 656 |
|
| 657 |
-
An
|
| 658 |
|
| 659 |
- in an expression, the function is the unique lookup result or the
|
| 660 |
selected member of a set of overloaded functions ([[basic.lookup]],
|
| 661 |
[[over.match]], [[over.over]]);
|
| 662 |
- the function is odr-used ([[basic.def.odr]]) or, if it appears in an
|
| 663 |
unevaluated operand, would be odr-used if the expression were
|
| 664 |
potentially-evaluated;
|
| 665 |
-
- the
|
| 666 |
-
|
| 667 |
-
function);
|
| 668 |
- the function is defined; or
|
| 669 |
-
- the
|
| 670 |
-
function that calls the function. A defaulted declaration
|
| 671 |
-
require the
|
| 672 |
-
evaluated until the implicit
|
| 673 |
-
function is needed, but an explicit *
|
| 674 |
-
the implicit
|
|
|
|
| 675 |
|
| 676 |
-
The
|
| 677 |
evaluated as described above only when needed; similarly, the
|
| 678 |
-
*
|
| 679 |
member function of a class template is instantiated only when needed.
|
| 680 |
|
| 681 |
-
In a *dynamic-exception-specification*, a *type-id* followed by an
|
| 682 |
-
ellipsis is a pack expansion ([[temp.variadic]]).
|
| 683 |
-
|
| 684 |
-
The use of *dynamic-exception-specification*s is deprecated (see Annex
|
| 685 |
-
[[depr]]).
|
| 686 |
-
|
| 687 |
## Special functions <a id="except.special">[[except.special]]</a>
|
| 688 |
|
| 689 |
-
The
|
| 690 |
-
|
| 691 |
-
handling mechanism
|
| 692 |
-
|
| 693 |
-
[[
|
| 694 |
-
|
| 695 |
-
handled exception.
|
| 696 |
|
| 697 |
### The `std::terminate()` function <a id="except.terminate">[[except.terminate]]</a>
|
| 698 |
|
| 699 |
In some situations exception handling must be abandoned for less subtle
|
| 700 |
-
error handling techniques.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 701 |
|
| 702 |
- when the exception handling mechanism, after completing the
|
| 703 |
initialization of the exception object but before activation of a
|
| 704 |
handler for the exception ([[except.throw]]), calls a function that
|
| 705 |
exits via an exception, or
|
| 706 |
- when the exception handling mechanism cannot find a handler for a
|
| 707 |
thrown exception ([[except.handle]]), or
|
| 708 |
- when the search for a handler ([[except.handle]]) encounters the
|
| 709 |
-
outermost block of a function with a
|
| 710 |
-
|
| 711 |
- when the destruction of an object during stack unwinding (
|
| 712 |
[[except.ctor]]) terminates by throwing an exception, or
|
| 713 |
- when initialization of a non-local variable with static or thread
|
| 714 |
-
storage duration ([[basic.start.
|
| 715 |
- when destruction of an object with static or thread storage duration
|
| 716 |
exits via an exception ([[basic.start.term]]), or
|
| 717 |
- when execution of a function registered with `std::atexit` or
|
| 718 |
`std::at_quick_exit` exits via an exception ([[support.start.term]]),
|
| 719 |
or
|
| 720 |
-
- when a *throw-expression* with no operand attempts
|
| 721 |
-
exception and no exception is being handled (
|
| 722 |
-
|
| 723 |
-
previously violated *dynamic-exception-specification*, and
|
| 724 |
-
`std::bad_exception` is not included in that
|
| 725 |
-
*dynamic-exception-specifica{-}tion* ([[except.unexpected]]), or
|
| 726 |
-
- when the implementation’s default unexpected exception handler is
|
| 727 |
-
called ([[unexpected.handler]]), or
|
| 728 |
- when the function `std::nested_exception::rethrow_nested` is called
|
| 729 |
for an object that has captured no exception ([[except.nested]]), or
|
| 730 |
- when execution of the initial function of a thread exits via an
|
| 731 |
exception ([[thread.thread.constr]]), or
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 732 |
- when the destructor or the copy assignment operator is invoked on an
|
| 733 |
object of type `std::thread` that refers to a joinable thread (
|
| 734 |
-
[[thread.thread.destr]], [[thread.thread.assign]])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 735 |
|
| 736 |
In such cases, `std::terminate()` is called ([[exception.terminate]]).
|
| 737 |
In the situation where no matching handler is found, it is
|
| 738 |
*implementation-defined* whether or not the stack is unwound before
|
| 739 |
`std::terminate()` is called. In the situation where the search for a
|
| 740 |
handler ([[except.handle]]) encounters the outermost block of a
|
| 741 |
-
function with a
|
| 742 |
-
|
| 743 |
-
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
`std::terminate()`.
|
| 749 |
|
| 750 |
-
### The `std::
|
| 751 |
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
| 755 |
-
|
| 756 |
-
|
| 757 |
-
|
| 758 |
-
|
| 759 |
-
|
| 760 |
-
case, the constraints in the following paragraph apply.
|
| 761 |
-
|
| 762 |
-
The `std::unexpected()` function shall not return, but it can throw (or
|
| 763 |
-
re-throw) an exception. If it throws a new exception which is allowed by
|
| 764 |
-
the exception specification which previously was violated, then the
|
| 765 |
-
search for another handler will continue at the call of the function
|
| 766 |
-
whose exception specification was violated. If it throws or rethrows an
|
| 767 |
-
exception that the * dynamic-exception-specification* does not allow
|
| 768 |
-
then the following happens: If the * dynamic-exception-specification*
|
| 769 |
-
does not include the class `std::bad_exception` ([[bad.exception]])
|
| 770 |
-
then the function `std::terminate()` is called, otherwise the thrown
|
| 771 |
-
exception is replaced by an implementation-defined object of the type
|
| 772 |
-
`std::bad_exception` and the search for another handler will continue at
|
| 773 |
-
the call of the function whose * dynamic-exception-specification* was
|
| 774 |
-
violated.
|
| 775 |
-
|
| 776 |
-
Thus, a *dynamic-exception-specification* guarantees that only the
|
| 777 |
-
listed exceptions will be thrown. If the
|
| 778 |
-
* dynamic-exception-specification* includes the type
|
| 779 |
-
`std::bad_exception` then any exception not on the list may be replaced
|
| 780 |
-
by `std::bad_exception` within the function `std::unexpected()`.
|
| 781 |
-
|
| 782 |
-
### The `std::uncaught_exception()` function <a id="except.uncaught">[[except.uncaught]]</a>
|
| 783 |
-
|
| 784 |
-
The function `std::uncaught_exception()` returns `true` after completing
|
| 785 |
-
the initialization of the exception object ([[except.throw]]) until
|
| 786 |
-
completing the activation of a handler for the exception (
|
| 787 |
-
[[except.handle]], [[uncaught]]). This includes stack unwinding. If the
|
| 788 |
-
exception is rethrown ([[except.throw]]), `std::uncaught_exception()`
|
| 789 |
-
returns `true` from the point of rethrow until the rethrown exception is
|
| 790 |
-
caught again.
|
| 791 |
|
| 792 |
<!-- Link reference definitions -->
|
| 793 |
-
[
|
|
|
|
| 794 |
[basic.def.odr]: basic.md#basic.def.odr
|
| 795 |
[basic.lookup]: basic.md#basic.lookup
|
| 796 |
-
[basic.start.
|
|
|
|
| 797 |
[basic.start.term]: basic.md#basic.start.term
|
| 798 |
[basic.stc.dynamic.allocation]: basic.md#basic.stc.dynamic.allocation
|
| 799 |
[basic.stc.dynamic.deallocation]: basic.md#basic.stc.dynamic.deallocation
|
| 800 |
-
[class.base.init]: special.md#class.base.init
|
| 801 |
[class.copy]: special.md#class.copy
|
| 802 |
[class.dtor]: special.md#class.dtor
|
| 803 |
-
[
|
| 804 |
-
[class.inhctor]: special.md#class.inhctor
|
| 805 |
-
[conv]: conv.md#conv
|
| 806 |
[conv.ptr]: conv.md#conv.ptr
|
|
|
|
|
|
|
| 807 |
[dcl.init]: dcl.md#dcl.init
|
| 808 |
-
[depr]: future.md#depr
|
| 809 |
[except]: #except
|
| 810 |
[except.ctor]: #except.ctor
|
| 811 |
[except.handle]: #except.handle
|
| 812 |
[except.nested]: language.md#except.nested
|
| 813 |
[except.spec]: #except.spec
|
| 814 |
[except.special]: #except.special
|
| 815 |
[except.terminate]: #except.terminate
|
| 816 |
[except.throw]: #except.throw
|
| 817 |
[except.uncaught]: #except.uncaught
|
| 818 |
-
[except.unexpected]: #except.unexpected
|
| 819 |
[exception.terminate]: language.md#exception.terminate
|
| 820 |
-
[
|
|
|
|
|
|
|
|
|
|
| 821 |
[expr.const]: expr.md#expr.const
|
| 822 |
[expr.dynamic.cast]: expr.md#expr.dynamic.cast
|
| 823 |
[expr.new]: expr.md#expr.new
|
|
|
|
| 824 |
[expr.typeid]: expr.md#expr.typeid
|
| 825 |
[futures]: thread.md#futures
|
|
|
|
|
|
|
| 826 |
[over.match]: over.md#over.match
|
| 827 |
[over.over]: over.md#over.over
|
| 828 |
[propagation]: language.md#propagation
|
| 829 |
-
[
|
| 830 |
-
[special]: special.md#special
|
| 831 |
[stmt.return]: stmt.md#stmt.return
|
| 832 |
[stmt.stmt]: stmt.md#stmt.stmt
|
| 833 |
[structure.specifications]: library.md#structure.specifications
|
| 834 |
[support.start.term]: language.md#support.start.term
|
| 835 |
-
[temp.
|
|
|
|
|
|
|
| 836 |
[thread.thread.assign]: thread.md#thread.thread.assign
|
| 837 |
[thread.thread.constr]: thread.md#thread.thread.constr
|
| 838 |
[thread.thread.destr]: thread.md#thread.thread.destr
|
| 839 |
-
[uncaught]: language.md#uncaught
|
| 840 |
-
[unexpected.handler]: future.md#unexpected.handler
|
|
|
|
| 32 |
attribute-specifier-seqₒₚₜ type-specifier-seq declarator
|
| 33 |
attribute-specifier-seqₒₚₜ type-specifier-seq abstract-declaratorₒₚₜ
|
| 34 |
'...'
|
| 35 |
```
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
The optional *attribute-specifier-seq* in an *exception-declaration*
|
| 38 |
appertains to the parameter of the catch clause ([[except.handle]]).
|
| 39 |
|
| 40 |
+
A *try-block* is a *statement* (Clause [[stmt.stmt]]).
|
| 41 |
+
|
| 42 |
+
[*Note 1*: Within this Clause “try block” is taken to mean both
|
| 43 |
+
*try-block* and *function-try-block*. — *end note*]
|
| 44 |
|
| 45 |
A `goto` or `switch` statement shall not be used to transfer control
|
| 46 |
into a try block or into a handler.
|
| 47 |
|
| 48 |
+
[*Example 1*:
|
| 49 |
+
|
| 50 |
``` cpp
|
| 51 |
void f() {
|
| 52 |
+
goto l1; // ill-formed
|
| 53 |
+
goto l2; // ill-formed
|
| 54 |
try {
|
| 55 |
goto l1; // OK
|
| 56 |
+
goto l2; // ill-formed
|
| 57 |
l1: ;
|
| 58 |
} catch (...) {
|
| 59 |
l2: ;
|
| 60 |
+
goto l1; // ill-formed
|
| 61 |
goto l2; // OK
|
| 62 |
}
|
| 63 |
}
|
| 64 |
```
|
| 65 |
|
| 66 |
+
— *end example*]
|
| 67 |
+
|
| 68 |
A `goto`, `break`, `return`, or `continue` statement can be used to
|
| 69 |
transfer control out of a try block or handler. When this happens, each
|
| 70 |
variable declared in the try block will be destroyed in the context that
|
| 71 |
directly contains its declaration.
|
| 72 |
|
| 73 |
+
[*Example 2*:
|
| 74 |
+
|
| 75 |
``` cpp
|
| 76 |
lab: try {
|
| 77 |
T1 t1;
|
| 78 |
try {
|
| 79 |
T2 t2;
|
|
|
|
| 82 |
} catch(...) { /* handler 2 */ }
|
| 83 |
} catch(...) { /* handler 1 */ }
|
| 84 |
```
|
| 85 |
|
| 86 |
Here, executing `goto lab;` will destroy first `t2`, then `t1`, assuming
|
| 87 |
+
the *condition* does not declare a variable. Any exception thrown while
|
| 88 |
+
destroying `t2` will result in executing `handler 2`; any exception
|
| 89 |
+
thrown while destroying `t1` will result in executing `handler 1`.
|
| 90 |
+
|
| 91 |
+
— *end example*]
|
| 92 |
|
| 93 |
A *function-try-block* associates a *handler-seq* with the
|
| 94 |
*ctor-initializer*, if present, and the *compound-statement*. An
|
| 95 |
exception thrown during the execution of the *compound-statement* or,
|
| 96 |
for constructors and destructors, during the initialization or
|
| 97 |
destruction, respectively, of the class’s subobjects, transfers control
|
| 98 |
to a handler in a *function-try-block* in the same way as an exception
|
| 99 |
thrown during the execution of a *try-block* transfers control to other
|
| 100 |
handlers.
|
| 101 |
|
| 102 |
+
[*Example 3*:
|
| 103 |
+
|
| 104 |
``` cpp
|
| 105 |
int f(int);
|
| 106 |
class C {
|
| 107 |
int i;
|
| 108 |
double d;
|
|
|
|
| 111 |
};
|
| 112 |
|
| 113 |
C::C(int ii, double id)
|
| 114 |
try : i(f(ii)), d(id) {
|
| 115 |
// constructor statements
|
| 116 |
+
} catch (...) {
|
| 117 |
+
// handles exceptions thrown from the ctor-initializer and from the constructor statements
|
|
|
|
|
|
|
| 118 |
}
|
| 119 |
```
|
| 120 |
|
| 121 |
+
— *end example*]
|
| 122 |
+
|
| 123 |
+
In this section, “before” and “after” refer to the “sequenced before”
|
| 124 |
+
relation ([[intro.execution]]).
|
| 125 |
+
|
| 126 |
## Throwing an exception <a id="except.throw">[[except.throw]]</a>
|
| 127 |
|
| 128 |
+
Throwing an exception transfers control to a handler.
|
| 129 |
+
|
| 130 |
+
[*Note 1*: An exception can be thrown from one of the following
|
| 131 |
+
contexts: *throw-expression*s ([[expr.throw]]), allocation functions (
|
| 132 |
+
[[basic.stc.dynamic.allocation]]), `dynamic_cast` (
|
| 133 |
+
[[expr.dynamic.cast]]), `typeid` ([[expr.typeid]]), *new-expression*s (
|
| 134 |
+
[[expr.new]]), and standard library functions (
|
| 135 |
+
[[structure.specifications]]). — *end note*]
|
| 136 |
+
|
| 137 |
+
An object is passed and the type of that object determines which
|
| 138 |
+
handlers can catch it.
|
| 139 |
+
|
| 140 |
+
[*Example 1*:
|
| 141 |
|
| 142 |
``` cpp
|
| 143 |
throw "Help!";
|
| 144 |
```
|
| 145 |
|
| 146 |
can be caught by a *handler* of `const` `char*` type:
|
| 147 |
|
| 148 |
``` cpp
|
| 149 |
try {
|
| 150 |
// ...
|
| 151 |
+
} catch(const char* p) {
|
|
|
|
| 152 |
// handle character string exceptions here
|
| 153 |
}
|
| 154 |
```
|
| 155 |
|
| 156 |
and
|
|
|
|
| 164 |
void f(double x) {
|
| 165 |
throw Overflow('+',x,3.45e107);
|
| 166 |
}
|
| 167 |
```
|
| 168 |
|
| 169 |
+
can be caught by a handler for exceptions of type `Overflow`:
|
| 170 |
|
| 171 |
``` cpp
|
| 172 |
try {
|
| 173 |
f(1.2);
|
| 174 |
} catch(Overflow& oo) {
|
| 175 |
// handle exceptions of type Overflow here
|
| 176 |
}
|
| 177 |
```
|
| 178 |
|
| 179 |
+
— *end example*]
|
| 180 |
+
|
| 181 |
When an exception is thrown, control is transferred to the nearest
|
| 182 |
handler with a matching type ([[except.handle]]); “nearest” means the
|
| 183 |
handler for which the *compound-statement* or *ctor-initializer*
|
| 184 |
following the `try` keyword was most recently entered by the thread of
|
| 185 |
control and not yet exited.
|
| 186 |
|
| 187 |
Throwing an exception copy-initializes ([[dcl.init]], [[class.copy]]) a
|
| 188 |
+
temporary object, called the *exception object*. An lvalue denoting the
|
| 189 |
+
temporary is used to initialize the variable declared in the matching
|
| 190 |
*handler* ([[except.handle]]). If the type of the exception object
|
| 191 |
would be an incomplete type or a pointer to an incomplete type other
|
| 192 |
+
than cv `void` the program is ill-formed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
The memory for the exception object is allocated in an unspecified way,
|
| 195 |
except as noted in [[basic.stc.dynamic.allocation]]. If a handler exits
|
| 196 |
by rethrowing, control is passed to another handler for the same
|
| 197 |
+
exception object. The points of potential destruction for the exception
|
| 198 |
+
object are:
|
| 199 |
+
|
| 200 |
+
- when an active handler for the exception exits by any means other than
|
| 201 |
+
rethrowing, immediately after the destruction of the object (if any)
|
| 202 |
+
declared in the *exception-declaration* in the handler;
|
| 203 |
+
- when an object of type `std::exception_ptr` ([[propagation]]) that
|
| 204 |
+
refers to the exception object is destroyed, before the destructor of
|
| 205 |
+
`std::exception_ptr` returns.
|
| 206 |
+
|
| 207 |
+
Among all points of potential destruction for the exception object,
|
| 208 |
+
there is an unspecified last one where the exception object is
|
| 209 |
+
destroyed. All other points happen before that last one (
|
| 210 |
+
[[intro.races]]).
|
| 211 |
+
|
| 212 |
+
[*Note 2*: No other thread synchronization is implied in exception
|
| 213 |
+
handling. — *end note*]
|
| 214 |
+
|
| 215 |
+
The implementation may then deallocate the memory for the exception
|
| 216 |
+
object; any such deallocation is done in an unspecified way.
|
| 217 |
+
|
| 218 |
+
[*Note 3*: A thrown exception does not propagate to other threads
|
| 219 |
unless caught, stored, and rethrown using appropriate library functions;
|
| 220 |
+
see [[propagation]] and [[futures]]. — *end note*]
|
| 221 |
|
| 222 |
When the thrown object is a class object, the constructor selected for
|
| 223 |
+
the copy-initialization as well as the constructor selected for a
|
| 224 |
+
copy-initialization considering the thrown object as an lvalue shall be
|
| 225 |
+
non-deleted and accessible, even if the copy/move operation is elided (
|
| 226 |
+
[[class.copy]]). The destructor is potentially invoked (
|
| 227 |
+
[[class.dtor]]).
|
| 228 |
|
| 229 |
An exception is considered caught when a handler for that exception
|
| 230 |
+
becomes active ([[except.handle]]).
|
|
|
|
| 231 |
|
| 232 |
+
[*Note 4*: An exception can have active handlers and still be
|
| 233 |
+
considered uncaught if it is rethrown. — *end note*]
|
| 234 |
+
|
| 235 |
+
If the exception handling mechanism handling an uncaught exception (
|
| 236 |
+
[[except.uncaught]]) directly invokes a function that exits via an
|
| 237 |
+
exception, `std::terminate` is called ([[except.terminate]]).
|
| 238 |
+
|
| 239 |
+
[*Example 2*:
|
| 240 |
|
| 241 |
``` cpp
|
| 242 |
struct C {
|
| 243 |
C() { }
|
| 244 |
C(const C&) {
|
| 245 |
+
if (std::uncaught_exceptions()) {
|
| 246 |
throw 0; // throw during copy to handler's exception-declaration object~([except.handle])
|
| 247 |
}
|
| 248 |
}
|
| 249 |
};
|
| 250 |
|
|
|
|
| 254 |
// exception-declaration object is not elided~([class.copy])
|
| 255 |
} catch(C) { }
|
| 256 |
}
|
| 257 |
```
|
| 258 |
|
| 259 |
+
— *end example*]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
|
| 261 |
+
[*Note 5*: Consequently, destructors should generally catch exceptions
|
| 262 |
+
and not let them propagate. — *end note*]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
|
| 264 |
## Constructors and destructors <a id="except.ctor">[[except.ctor]]</a>
|
| 265 |
|
| 266 |
As control passes from the point where an exception is thrown to a
|
| 267 |
+
handler, destructors are invoked by a process, specified in this
|
| 268 |
+
section, called *stack unwinding*.
|
| 269 |
+
|
| 270 |
+
The destructor is invoked for each automatic object of class type
|
| 271 |
+
constructed, but not yet destroyed, since the try block was entered. If
|
| 272 |
+
an exception is thrown during the destruction of temporaries or local
|
| 273 |
+
variables for a `return` statement ([[stmt.return]]), the destructor
|
| 274 |
+
for the returned object (if any) is also invoked. The objects are
|
| 275 |
+
destroyed in the reverse order of the completion of their construction.
|
| 276 |
+
|
| 277 |
+
[*Example 1*:
|
| 278 |
+
|
| 279 |
+
``` cpp
|
| 280 |
+
struct A { };
|
| 281 |
+
|
| 282 |
+
struct Y { ~Y() noexcept(false) { throw 0; } };
|
| 283 |
+
|
| 284 |
+
A f() {
|
| 285 |
+
try {
|
| 286 |
+
A a;
|
| 287 |
+
Y y;
|
| 288 |
+
A b;
|
| 289 |
+
return {}; // #1
|
| 290 |
+
} catch (...) {
|
| 291 |
+
}
|
| 292 |
+
return {}; // #2
|
| 293 |
+
}
|
| 294 |
+
```
|
| 295 |
+
|
| 296 |
+
At \#1, the returned object of type `A` is constructed. Then, the local
|
| 297 |
+
variable `b` is destroyed ([[stmt.jump]]). Next, the local variable `y`
|
| 298 |
+
is destroyed, causing stack unwinding, resulting in the destruction of
|
| 299 |
+
the returned object, followed by the destruction of the local variable
|
| 300 |
+
`a`. Finally, the returned object is constructed again at \#2.
|
| 301 |
+
|
| 302 |
+
— *end example*]
|
| 303 |
+
|
| 304 |
+
If the initialization or destruction of an object other than by
|
| 305 |
+
delegating constructor is terminated by an exception, the destructor is
|
| 306 |
+
invoked for each of the object’s direct subobjects and, for a complete
|
| 307 |
+
object, virtual base class subobjects, whose initialization has
|
| 308 |
+
completed ([[dcl.init]]) and whose destructor has not yet begun
|
| 309 |
+
execution, except that in the case of destruction, the variant members
|
| 310 |
+
of a union-like class are not destroyed. The subobjects are destroyed in
|
| 311 |
+
the reverse order of the completion of their construction. Such
|
| 312 |
+
destruction is sequenced before entering a handler of the
|
| 313 |
+
*function-try-block* of the constructor or destructor, if any.
|
| 314 |
+
|
| 315 |
+
If the *compound-statement* of the *function-body* of a delegating
|
| 316 |
+
constructor for an object exits via an exception, the object’s
|
| 317 |
+
destructor is invoked. Such destruction is sequenced before entering a
|
| 318 |
+
handler of the *function-try-block* of a delegating constructor for that
|
| 319 |
+
object, if any.
|
| 320 |
+
|
| 321 |
+
[*Note 1*: If the object was allocated by a *new-expression* (
|
| 322 |
+
[[expr.new]]), the matching deallocation function (
|
| 323 |
+
[[basic.stc.dynamic.deallocation]]), if any, is called to free the
|
| 324 |
+
storage occupied by the object. — *end note*]
|
| 325 |
|
| 326 |
## Handling an exception <a id="except.handle">[[except.handle]]</a>
|
| 327 |
|
| 328 |
The *exception-declaration* in a *handler* describes the type(s) of
|
| 329 |
exceptions that can cause that *handler* to be entered. The
|
|
|
|
| 331 |
class type, or an rvalue reference type. The *exception-declaration*
|
| 332 |
shall not denote a pointer or reference to an incomplete type, other
|
| 333 |
than `void*`, `const` `void*`, `volatile` `void*`, or `const` `volatile`
|
| 334 |
`void*`.
|
| 335 |
|
| 336 |
+
A handler of type “array of `T`” or function type `T` is adjusted to be
|
| 337 |
+
of type “pointer to `T`”.
|
|
|
|
| 338 |
|
| 339 |
A *handler* is a match for an exception object of type `E` if
|
| 340 |
|
| 341 |
+
- The *handler* is of type cv `T` or cv `T&` and `E` and `T` are the
|
| 342 |
+
same type (ignoring the top-level *cv-qualifier*s), or
|
| 343 |
+
- the *handler* is of type cv `T` or cv `T&` and `T` is an unambiguous
|
| 344 |
+
public base class of `E`, or
|
| 345 |
+
- the *handler* is of type cv `T` or `const T&` where `T` is a pointer
|
| 346 |
+
or pointer to member type and `E` is a pointer or pointer to member
|
| 347 |
+
type that can be converted to `T` by one or more of
|
| 348 |
- a standard pointer conversion ([[conv.ptr]]) not involving
|
| 349 |
conversions to pointers to private or protected or ambiguous classes
|
| 350 |
+
- a function pointer conversion ([[conv.fctptr]])
|
| 351 |
+
- a qualification conversion ([[conv.qual]]), or
|
| 352 |
+
- the *handler* is of type cv `T` or `const T&` where `T` is a pointer
|
| 353 |
or pointer to member type and `E` is `std::nullptr_t`.
|
| 354 |
|
| 355 |
+
[*Note 1*: A *throw-expression* whose operand is an integer literal
|
| 356 |
+
with value zero does not match a handler of pointer or pointer to member
|
| 357 |
+
type. A handler of reference to array or function type is never a match
|
| 358 |
+
for any exception object ([[expr.throw]]). — *end note*]
|
| 359 |
+
|
| 360 |
+
[*Example 1*:
|
| 361 |
|
| 362 |
``` cpp
|
| 363 |
+
class Matherr { ... virtual void vf(); };
|
| 364 |
+
class Overflow: public Matherr { ... };
|
| 365 |
+
class Underflow: public Matherr { ... };
|
| 366 |
+
class Zerodivide: public Matherr { ... };
|
| 367 |
|
| 368 |
void f() {
|
| 369 |
try {
|
| 370 |
g();
|
| 371 |
} catch (Overflow oo) {
|
|
|
|
| 379 |
Here, the `Overflow` handler will catch exceptions of type `Overflow`
|
| 380 |
and the `Matherr` handler will catch exceptions of type `Matherr` and of
|
| 381 |
all types publicly derived from `Matherr` including exceptions of type
|
| 382 |
`Underflow` and `Zerodivide`.
|
| 383 |
|
| 384 |
+
— *end example*]
|
| 385 |
+
|
| 386 |
+
The handlers for a try block are tried in order of appearance.
|
| 387 |
+
|
| 388 |
+
[*Note 2*: This makes it possible to write handlers that can never be
|
| 389 |
+
executed, for example by placing a handler for a final derived class
|
| 390 |
+
after a handler for a corresponding unambiguous public base
|
| 391 |
+
class. — *end note*]
|
| 392 |
|
| 393 |
A `...` in a handler’s *exception-declaration* functions similarly to
|
| 394 |
`...` in a function parameter declaration; it specifies a match for any
|
| 395 |
exception. If present, a `...` handler shall be the last handler for its
|
| 396 |
try block.
|
|
|
|
| 398 |
If no match is found among the handlers for a try block, the search for
|
| 399 |
a matching handler continues in a dynamically surrounding try block of
|
| 400 |
the same thread.
|
| 401 |
|
| 402 |
A handler is considered active when initialization is complete for the
|
| 403 |
+
parameter (if any) of the catch clause.
|
| 404 |
+
|
| 405 |
+
[*Note 3*: The stack will have been unwound at that
|
| 406 |
+
point. — *end note*]
|
| 407 |
+
|
| 408 |
+
Also, an implicit handler is considered active when `std::terminate()`
|
| 409 |
+
is entered due to a throw. A handler is no longer considered active when
|
| 410 |
+
the catch clause exits.
|
| 411 |
|
| 412 |
The exception with the most recently activated handler that is still
|
| 413 |
active is called the *currently handled exception*.
|
| 414 |
|
| 415 |
If no matching handler is found, the function `std::terminate()` is
|
|
|
|
| 418 |
|
| 419 |
Referring to any non-static member or base class of an object in the
|
| 420 |
handler for a *function-try-block* of a constructor or destructor for
|
| 421 |
that object results in undefined behavior.
|
| 422 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 423 |
The scope and lifetime of the parameters of a function or constructor
|
| 424 |
extend into the handlers of a *function-try-block*.
|
| 425 |
|
| 426 |
Exceptions thrown in destructors of objects with static storage duration
|
| 427 |
or in constructors of namespace-scope objects with static storage
|
| 428 |
+
duration are not caught by a *function-try-block* on the `main`
|
| 429 |
+
function ([[basic.start.main]]). Exceptions thrown in destructors of
|
| 430 |
+
objects with thread storage duration or in constructors of
|
| 431 |
+
namespace-scope objects with thread storage duration are not caught by a
|
| 432 |
+
*function-try-block* on the initial function of the thread.
|
| 433 |
|
| 434 |
If a return statement appears in a handler of the *function-try-block*
|
| 435 |
of a constructor, the program is ill-formed.
|
| 436 |
|
| 437 |
The currently handled exception is rethrown if control reaches the end
|
| 438 |
of a handler of the *function-try-block* of a constructor or destructor.
|
| 439 |
+
Otherwise, flowing off the end of the *compound-statement* of a
|
| 440 |
+
*handler* of a *function-try-block* is equivalent to flowing off the end
|
| 441 |
+
of the *compound-statement* of that function (see [[stmt.return]]).
|
|
|
|
|
|
|
| 442 |
|
| 443 |
+
The variable declared by the *exception-declaration*, of type cv `T` or
|
| 444 |
+
cv `T&`, is initialized from the exception object, of type `E`, as
|
| 445 |
follows:
|
| 446 |
|
| 447 |
- if `T` is a base class of `E`, the variable is copy-initialized (
|
| 448 |
[[dcl.init]]) from the corresponding base class subobject of the
|
| 449 |
exception object;
|
|
|
|
| 458 |
object, any changes to the referenced object are changes to the
|
| 459 |
exception object and will have effect should that object be rethrown.
|
| 460 |
|
| 461 |
## Exception specifications <a id="except.spec">[[except.spec]]</a>
|
| 462 |
|
| 463 |
+
The predicate indicating whether a function cannot exit via an exception
|
| 464 |
+
is called the *exception specification* of the function. If the
|
| 465 |
+
predicate is false, the function has a *potentially-throwing exception
|
| 466 |
+
specification*, otherwise it has a *non-throwing exception
|
| 467 |
+
specification*. The exception specification is either defined
|
| 468 |
+
implicitly, or defined explicitly by using a *noexcept-specifier* as a
|
| 469 |
+
suffix of a function declarator ([[dcl.fct]]).
|
| 470 |
|
| 471 |
``` bnf
|
| 472 |
+
noexcept-specifier:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 473 |
'noexcept' '(' constant-expression ')'
|
| 474 |
'noexcept'
|
| 475 |
+
'throw' '(' ')'
|
| 476 |
```
|
| 477 |
|
| 478 |
+
In a *noexcept-specifier*, the *constant-expression*, if supplied, shall
|
| 479 |
+
be a contextually converted constant expression of type `bool` (
|
| 480 |
+
[[expr.const]]); that constant expression is the exception specification
|
| 481 |
+
of the function type in which the *noexcept-specifier* appears. A `(`
|
| 482 |
+
token that follows `noexcept` is part of the *noexcept-specifier* and
|
| 483 |
+
does not commence an initializer ([[dcl.init]]). The
|
| 484 |
+
*noexcept-specifier* `noexcept` without a *constant-expression* is
|
| 485 |
+
equivalent to the *noexcept-specifier* `noexcept(true)`. The
|
| 486 |
+
*noexcept-specifier* `throw()` is deprecated ([[depr.except.spec]]),
|
| 487 |
+
and equivalent to the *noexcept-specifier* `noexcept(true)`.
|
| 488 |
+
|
| 489 |
+
If a declaration of a function does not have a *noexcept-specifier*, the
|
| 490 |
+
declaration has a potentially throwing exception specification unless it
|
| 491 |
+
is a destructor or a deallocation function or is defaulted on its first
|
| 492 |
+
declaration, in which cases the exception specfication is as specified
|
| 493 |
+
below and no other declaration for that function shall have a
|
| 494 |
+
*noexcept-specifier*. In an explicit instantiation ([[temp.explicit]])
|
| 495 |
+
a *noexcept-specifier* may be specified, but is not required. If a
|
| 496 |
+
*noexcept-specifier* is specified in an explicit instantiation
|
| 497 |
+
directive, the exception specification shall be the same as the
|
| 498 |
+
exception specification of all other declarations of that function. A
|
| 499 |
+
diagnostic is required only if the exception specifications are not the
|
| 500 |
+
same within a single translation unit.
|
| 501 |
+
|
| 502 |
+
If a virtual function has a non-throwing exception specification, all
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 503 |
declarations, including the definition, of any function that overrides
|
| 504 |
+
that virtual function in any derived class shall have a non-throwing
|
| 505 |
+
exception specification, unless the overriding function is defined as
|
| 506 |
+
deleted.
|
| 507 |
+
|
| 508 |
+
[*Example 1*:
|
| 509 |
|
| 510 |
``` cpp
|
| 511 |
struct B {
|
| 512 |
+
virtual void f() noexcept;
|
| 513 |
virtual void g();
|
| 514 |
+
virtual void h() noexcept = delete;
|
| 515 |
};
|
| 516 |
|
| 517 |
struct D: B {
|
| 518 |
void f(); // ill-formed
|
| 519 |
+
void g() noexcept; // OK
|
| 520 |
+
void h() = delete; // OK
|
| 521 |
};
|
| 522 |
```
|
| 523 |
|
| 524 |
+
The declaration of `D::f` is ill-formed because it has a
|
| 525 |
+
potentially-throwing exception specification, whereas `B::f` has a
|
| 526 |
+
non-throwing exception specification.
|
|
|
|
|
|
|
|
|
|
| 527 |
|
| 528 |
+
— *end example*]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 529 |
|
| 530 |
Whenever an exception is thrown and the search for a handler (
|
| 531 |
+
[[except.handle]]) encounters the outermost block of a function with a
|
| 532 |
+
non-throwing exception specification, the function `std::terminate()` is
|
| 533 |
+
called ([[except.terminate]]).
|
| 534 |
|
| 535 |
+
[*Note 1*: An implementation shall not reject an expression merely
|
| 536 |
+
because, when executed, it throws or might throw an exception from a
|
| 537 |
+
function with a non-throwing exception specification. — *end note*]
|
| 538 |
+
|
| 539 |
+
[*Example 2*:
|
| 540 |
|
| 541 |
``` cpp
|
| 542 |
+
extern void f(); // potentially-throwing
|
|
|
|
|
|
|
|
|
|
| 543 |
|
| 544 |
+
void g() noexcept {
|
| 545 |
+
f(); // valid, even if f throws
|
| 546 |
+
throw 42; // valid, effectively a call to std::terminate
|
|
|
|
|
|
|
| 547 |
}
|
| 548 |
```
|
| 549 |
|
| 550 |
+
The call to `f` is well-formed even though, when called, `f` might throw
|
| 551 |
+
an exception.
|
|
|
|
| 552 |
|
| 553 |
+
— *end example*]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 554 |
|
| 555 |
+
An expression `e` is *potentially-throwing* if
|
|
|
|
|
|
|
| 556 |
|
| 557 |
+
- `e` is a function call ([[expr.call]]) whose *postfix-expression* has
|
| 558 |
+
a function type, or a pointer-to-function type, with a
|
| 559 |
+
potentially-throwing exception specification, or
|
| 560 |
+
- `e` implicitly invokes a function (such as an overloaded operator, an
|
| 561 |
+
allocation function in a *new-expression*, a constructor for a
|
| 562 |
+
function argument, or a destructor if `e` is a full-expression (
|
| 563 |
+
[[intro.execution]])) that is potentially-throwing, or
|
| 564 |
+
- `e` is a *throw-expression* ([[expr.throw]]), or
|
| 565 |
+
- `e` is a `dynamic_cast` expression that casts to a reference type and
|
| 566 |
+
requires a runtime check ([[expr.dynamic.cast]]), or
|
| 567 |
+
- `e` is a `typeid` expression applied to a (possibly parenthesized)
|
| 568 |
+
built-in unary `*` operator applied to a pointer to a polymorphic
|
| 569 |
+
class type ([[expr.typeid]]), or
|
| 570 |
+
- any of the immediate subexpressions ([[intro.execution]]) of `e` is
|
| 571 |
+
potentially-throwing.
|
| 572 |
|
| 573 |
+
An implicitly-declared constructor for a class `X`, or a constructor
|
| 574 |
+
without a *noexcept-specifier* that is defaulted on its first
|
| 575 |
+
declaration, has a potentially-throwing exception specification if and
|
| 576 |
+
only if any of the following constructs is potentially-throwing:
|
| 577 |
+
|
| 578 |
+
- a constructor selected by overload resolution in the implicit
|
| 579 |
+
definition of the constructor for class `X` to initialize a
|
| 580 |
+
potentially constructed subobject, or
|
| 581 |
+
- a subexpression of such an initialization, such as a default argument
|
| 582 |
+
expression, or,
|
| 583 |
+
- for a default constructor, a default member initializer.
|
| 584 |
+
|
| 585 |
+
[*Note 2*: Even though destructors for fully-constructed subobjects are
|
| 586 |
+
invoked when an exception is thrown during the execution of a
|
| 587 |
+
constructor ([[except.ctor]]), their exception specifications do not
|
| 588 |
+
contribute to the exception specification of the constructor, because an
|
| 589 |
+
exception thrown from such a destructor would call `std::terminate`
|
| 590 |
+
rather than escape the constructor ([[except.throw]],
|
| 591 |
+
[[except.terminate]]). — *end note*]
|
| 592 |
|
| 593 |
+
The exception specification for an implicitly-declared destructor, or a
|
| 594 |
+
destructor without a *noexcept-specifier*, is potentially-throwing if
|
| 595 |
+
and only if any of the destructors for any of its potentially
|
| 596 |
+
constructed subojects is potentially throwing.
|
| 597 |
|
| 598 |
+
The exception specification for an implicitly-declared assignment
|
| 599 |
+
operator, or an assignment-operator without a *noexcept-specifier* that
|
| 600 |
+
is defaulted on its first declaration, is potentially-throwing if and
|
| 601 |
+
only if the invocation of any assignment operator in the implicit
|
| 602 |
+
definition is potentially-throwing.
|
|
|
|
|
|
|
|
|
|
| 603 |
|
| 604 |
+
A deallocation function ([[basic.stc.dynamic.deallocation]]) with no
|
| 605 |
+
explicit *noexcept-specifier* has a non-throwing exception
|
| 606 |
+
specification.
|
| 607 |
|
| 608 |
+
[*Example 3*:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 609 |
|
| 610 |
``` cpp
|
| 611 |
struct A {
|
| 612 |
+
A(int = (A(5), 0)) noexcept;
|
| 613 |
+
A(const A&) noexcept;
|
| 614 |
+
A(A&&) noexcept;
|
| 615 |
+
~A();
|
| 616 |
};
|
| 617 |
struct B {
|
| 618 |
B() throw();
|
| 619 |
+
B(const B&) = default; // implicit exception specification is noexcept(true)
|
| 620 |
+
B(B&&, int = (throw Y(), 0)) noexcept;
|
| 621 |
+
~B() noexcept(false);
|
| 622 |
};
|
| 623 |
+
int n = 7;
|
| 624 |
struct D : public A, public B {
|
| 625 |
+
int * p = new int[n];
|
| 626 |
+
// D::D() potentially-throwing, as the new operator may throw bad_alloc or bad_array_new_length
|
| 627 |
+
// D::D(const D&) non-throwing
|
| 628 |
+
// D::D(D&&) potentially-throwing, as the default argument for B's constructor may throw
|
| 629 |
+
// D::~D() potentially-throwing
|
| 630 |
};
|
| 631 |
```
|
| 632 |
|
| 633 |
+
Furthermore, if `A::~A()` were virtual, the program would be ill-formed
|
| 634 |
+
since a function that overrides a virtual function from a base class
|
| 635 |
+
shall not have a potentially-throwing exception specification if the
|
| 636 |
+
base class function has a non-throwing exception specification.
|
|
|
|
| 637 |
|
| 638 |
+
— *end example*]
|
|
|
|
|
|
|
| 639 |
|
| 640 |
+
An exception specification is considered to be *needed* when:
|
| 641 |
|
| 642 |
- in an expression, the function is the unique lookup result or the
|
| 643 |
selected member of a set of overloaded functions ([[basic.lookup]],
|
| 644 |
[[over.match]], [[over.over]]);
|
| 645 |
- the function is odr-used ([[basic.def.odr]]) or, if it appears in an
|
| 646 |
unevaluated operand, would be odr-used if the expression were
|
| 647 |
potentially-evaluated;
|
| 648 |
+
- the exception specification is compared to that of another declaration
|
| 649 |
+
(e.g., an explicit specialization or an overriding virtual function);
|
|
|
|
| 650 |
- the function is defined; or
|
| 651 |
+
- the exception specification is needed for a defaulted special member
|
| 652 |
+
function that calls the function. \[*Note 3*: A defaulted declaration
|
| 653 |
+
does not require the exception specification of a base member function
|
| 654 |
+
to be evaluated until the implicit exception specification of the
|
| 655 |
+
derived function is needed, but an explicit *noexcept-specifier* needs
|
| 656 |
+
the implicit exception specification to compare
|
| 657 |
+
against. — *end note*]
|
| 658 |
|
| 659 |
+
The exception specification of a defaulted special member function is
|
| 660 |
evaluated as described above only when needed; similarly, the
|
| 661 |
+
*noexcept-specifier* of a specialization of a function template or
|
| 662 |
member function of a class template is instantiated only when needed.
|
| 663 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
## Special functions <a id="except.special">[[except.special]]</a>
|
| 665 |
|
| 666 |
+
The function `std::terminate()` ([[except.terminate]]) is used by the
|
| 667 |
+
exception handling mechanism for coping with errors related to the
|
| 668 |
+
exception handling mechanism itself. The function
|
| 669 |
+
`std::current_exception()` ([[propagation]]) and the class
|
| 670 |
+
`std::nested_exception` ([[except.nested]]) can be used by a program to
|
| 671 |
+
capture the currently handled exception.
|
|
|
|
| 672 |
|
| 673 |
### The `std::terminate()` function <a id="except.terminate">[[except.terminate]]</a>
|
| 674 |
|
| 675 |
In some situations exception handling must be abandoned for less subtle
|
| 676 |
+
error handling techniques.
|
| 677 |
+
|
| 678 |
+
[*Note 1*:
|
| 679 |
+
|
| 680 |
+
These situations are:
|
| 681 |
|
| 682 |
- when the exception handling mechanism, after completing the
|
| 683 |
initialization of the exception object but before activation of a
|
| 684 |
handler for the exception ([[except.throw]]), calls a function that
|
| 685 |
exits via an exception, or
|
| 686 |
- when the exception handling mechanism cannot find a handler for a
|
| 687 |
thrown exception ([[except.handle]]), or
|
| 688 |
- when the search for a handler ([[except.handle]]) encounters the
|
| 689 |
+
outermost block of a function with a non-throwing exception
|
| 690 |
+
specification ([[except.spec]]), or
|
| 691 |
- when the destruction of an object during stack unwinding (
|
| 692 |
[[except.ctor]]) terminates by throwing an exception, or
|
| 693 |
- when initialization of a non-local variable with static or thread
|
| 694 |
+
storage duration ([[basic.start.dynamic]]) exits via an exception, or
|
| 695 |
- when destruction of an object with static or thread storage duration
|
| 696 |
exits via an exception ([[basic.start.term]]), or
|
| 697 |
- when execution of a function registered with `std::atexit` or
|
| 698 |
`std::at_quick_exit` exits via an exception ([[support.start.term]]),
|
| 699 |
or
|
| 700 |
+
- when a *throw-expression* ([[expr.throw]]) with no operand attempts
|
| 701 |
+
to rethrow an exception and no exception is being handled (
|
| 702 |
+
[[except.throw]]), or
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 703 |
- when the function `std::nested_exception::rethrow_nested` is called
|
| 704 |
for an object that has captured no exception ([[except.nested]]), or
|
| 705 |
- when execution of the initial function of a thread exits via an
|
| 706 |
exception ([[thread.thread.constr]]), or
|
| 707 |
+
- for a parallel algorithm whose `ExecutionPolicy` specifies such
|
| 708 |
+
behavior ([[execpol.seq]], [[execpol.par]], [[execpol.parunseq]]),
|
| 709 |
+
when execution of an element access function (
|
| 710 |
+
[[algorithms.parallel.defns]]) of the parallel algorithm exits via an
|
| 711 |
+
exception ([[algorithms.parallel.exceptions]]), or
|
| 712 |
- when the destructor or the copy assignment operator is invoked on an
|
| 713 |
object of type `std::thread` that refers to a joinable thread (
|
| 714 |
+
[[thread.thread.destr]], [[thread.thread.assign]]), or
|
| 715 |
+
- when a call to a `wait()`, `wait_until()`, or `wait_for()` function on
|
| 716 |
+
a condition variable ([[thread.condition.condvar]],
|
| 717 |
+
[[thread.condition.condvarany]]) fails to meet a postcondition.
|
| 718 |
+
|
| 719 |
+
— *end note*]
|
| 720 |
|
| 721 |
In such cases, `std::terminate()` is called ([[exception.terminate]]).
|
| 722 |
In the situation where no matching handler is found, it is
|
| 723 |
*implementation-defined* whether or not the stack is unwound before
|
| 724 |
`std::terminate()` is called. In the situation where the search for a
|
| 725 |
handler ([[except.handle]]) encounters the outermost block of a
|
| 726 |
+
function with a non-throwing exception specification ([[except.spec]]),
|
| 727 |
+
it is *implementation-defined* whether the stack is unwound, unwound
|
| 728 |
+
partially, or not unwound at all before `std::terminate()` is called. In
|
| 729 |
+
all other situations, the stack shall not be unwound before
|
| 730 |
+
`std::terminate()` is called. An implementation is not permitted to
|
| 731 |
+
finish stack unwinding prematurely based on a determination that the
|
| 732 |
+
unwind process will eventually cause a call to `std::terminate()`.
|
|
|
|
| 733 |
|
| 734 |
+
### The `std::uncaught_exceptions()` function <a id="except.uncaught">[[except.uncaught]]</a>
|
| 735 |
|
| 736 |
+
An exception is considered uncaught after completing the initialization
|
| 737 |
+
of the exception object ([[except.throw]]) until completing the
|
| 738 |
+
activation of a handler for the exception ([[except.handle]]). This
|
| 739 |
+
includes stack unwinding. If an exception is rethrown ([[expr.throw]],
|
| 740 |
+
[[propagation]]), it is considered uncaught from the point of rethrow
|
| 741 |
+
until the rethrown exception is caught. The function
|
| 742 |
+
`std::uncaught_exceptions()` ([[uncaught.exceptions]]) returns the
|
| 743 |
+
number of uncaught exceptions in the current thread.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 744 |
|
| 745 |
<!-- Link reference definitions -->
|
| 746 |
+
[algorithms.parallel.defns]: algorithms.md#algorithms.parallel.defns
|
| 747 |
+
[algorithms.parallel.exceptions]: algorithms.md#algorithms.parallel.exceptions
|
| 748 |
[basic.def.odr]: basic.md#basic.def.odr
|
| 749 |
[basic.lookup]: basic.md#basic.lookup
|
| 750 |
+
[basic.start.dynamic]: basic.md#basic.start.dynamic
|
| 751 |
+
[basic.start.main]: basic.md#basic.start.main
|
| 752 |
[basic.start.term]: basic.md#basic.start.term
|
| 753 |
[basic.stc.dynamic.allocation]: basic.md#basic.stc.dynamic.allocation
|
| 754 |
[basic.stc.dynamic.deallocation]: basic.md#basic.stc.dynamic.deallocation
|
|
|
|
| 755 |
[class.copy]: special.md#class.copy
|
| 756 |
[class.dtor]: special.md#class.dtor
|
| 757 |
+
[conv.fctptr]: conv.md#conv.fctptr
|
|
|
|
|
|
|
| 758 |
[conv.ptr]: conv.md#conv.ptr
|
| 759 |
+
[conv.qual]: conv.md#conv.qual
|
| 760 |
+
[dcl.fct]: dcl.md#dcl.fct
|
| 761 |
[dcl.init]: dcl.md#dcl.init
|
| 762 |
+
[depr.except.spec]: future.md#depr.except.spec
|
| 763 |
[except]: #except
|
| 764 |
[except.ctor]: #except.ctor
|
| 765 |
[except.handle]: #except.handle
|
| 766 |
[except.nested]: language.md#except.nested
|
| 767 |
[except.spec]: #except.spec
|
| 768 |
[except.special]: #except.special
|
| 769 |
[except.terminate]: #except.terminate
|
| 770 |
[except.throw]: #except.throw
|
| 771 |
[except.uncaught]: #except.uncaught
|
|
|
|
| 772 |
[exception.terminate]: language.md#exception.terminate
|
| 773 |
+
[execpol.par]: utilities.md#execpol.par
|
| 774 |
+
[execpol.parunseq]: utilities.md#execpol.parunseq
|
| 775 |
+
[execpol.seq]: utilities.md#execpol.seq
|
| 776 |
+
[expr.call]: expr.md#expr.call
|
| 777 |
[expr.const]: expr.md#expr.const
|
| 778 |
[expr.dynamic.cast]: expr.md#expr.dynamic.cast
|
| 779 |
[expr.new]: expr.md#expr.new
|
| 780 |
+
[expr.throw]: expr.md#expr.throw
|
| 781 |
[expr.typeid]: expr.md#expr.typeid
|
| 782 |
[futures]: thread.md#futures
|
| 783 |
+
[intro.execution]: intro.md#intro.execution
|
| 784 |
+
[intro.races]: intro.md#intro.races
|
| 785 |
[over.match]: over.md#over.match
|
| 786 |
[over.over]: over.md#over.over
|
| 787 |
[propagation]: language.md#propagation
|
| 788 |
+
[stmt.jump]: stmt.md#stmt.jump
|
|
|
|
| 789 |
[stmt.return]: stmt.md#stmt.return
|
| 790 |
[stmt.stmt]: stmt.md#stmt.stmt
|
| 791 |
[structure.specifications]: library.md#structure.specifications
|
| 792 |
[support.start.term]: language.md#support.start.term
|
| 793 |
+
[temp.explicit]: temp.md#temp.explicit
|
| 794 |
+
[thread.condition.condvar]: thread.md#thread.condition.condvar
|
| 795 |
+
[thread.condition.condvarany]: thread.md#thread.condition.condvarany
|
| 796 |
[thread.thread.assign]: thread.md#thread.thread.assign
|
| 797 |
[thread.thread.constr]: thread.md#thread.thread.constr
|
| 798 |
[thread.thread.destr]: thread.md#thread.thread.destr
|
| 799 |
+
[uncaught.exceptions]: language.md#uncaught.exceptions
|
|
|