Lists the exceptions that a function might directly or indirectly throw.
throw( type-id-list (optional)) | (1) | (deprecated in C++11) (removed in C++17) |
type-id-list | - | comma-separated list of type-ids, a type-id representing a pack expansion is followed by an ellipsis (...) (since C++11) |
An explicit dynamic exception specification shall appear only on a function declarator for a function type, pointer to function type, reference to function type, or pointer to member function type that is the top-level type of a declaration or definition, or on such a type appearing as a parameter or return type in a function declarator.
void f() throw(int); // OK: function declaration void (*pf)() throw (int); // OK: pointer to function declaration void g(void pfa() throw(int)); // OK: pointer to function parameter declaration typedef int (*pf)() throw(int); // Error: typedef declaration
If a function is declared with type T
listed in its dynamic exception specification, the function may throw exceptions of that type or a type derived from it.
Incomplete types, pointers or references to incomplete types other than cv void*
, and rvalue reference types (since C++11) are not allowed in the exception specification. Array and function types, if used, are adjusted to corresponding pointer types, top level cv-qualifications are also dropped. parameter packs are allowed (since C++11).
A dynamic exception specification whose set of adjusted types is empty (after any packs are expanded) (since C++11) is non-throwing. A function with a non-throwing dynamic exception specification does not allow any exceptions.
A dynamic exception specification is not considered part of a function’s type.
If the function throws an exception of the type not listed in its exception specification, the function std::unexpected
is called. The default function calls std::terminate
, but it may be replaced by a user-provided function (via std::set_unexpected
) which may call std::terminate
or throw an exception. If the exception thrown from std::unexpected
is accepted by the exception specification, stack unwinding continues as usual. If it isn't, but std::bad_exception
is allowed by the exception specification, std::bad_exception
is thrown. Otherwise, std::terminate
is called.
Each function f
, pointer to function pf
, and pointer to member function pmf
has a set of potential exceptions, which consists of types that might be thrown. Set of all types indicates that any exception may be thrown. This set is defined as follows:
f
, pf
, or pmf
uses a dynamic exception specification that does not allow all exceptions (until C++11), the set consists of the types listed in that specification. 2) Otherwise, if the declaration of f , pf , or pmf uses noexcept(true) , the set is empty. | (since C++11) |
Note: for implicitly-declared special member functions (constructors, assignment operators, and destructors) and for the inheriting constructors (since C++11), the set of potential exceptions is a combination of the sets of the potential exceptions of everything they would call: constructors/assignment operators/destructors of non-variant non-static data members, direct bases, and, where appropriate, virtual bases (including default argument expressions, as always).
Each expression e
has a set of potential exceptions. The set is empty if e
is a core constant expression, otherwise, it is the union of the sets of potential exceptions of all immediate subexpressions of e
(including default argument expressions), combined with another set that depends on the form of e
, as follows:
e
is a function call expression, let g
denote the function, function pointer, or pointer to member function that is that is called, then g
uses a dynamic exception specification, the set of potential exceptions of g
is added to the set;
| (since C++11) |
e
calls a function implicitly (it's an operator expression and the operator is overloaded, it is a new-expression and the allocation function is overloaded, or it is a full expression and the destructor of a temporary is called), then the set is the set of that function.e
is a throw-expression, the set is the exception that would be initialized by its operand, or the set of all types for the re-throwing throw-expression (with no operand).e
is a typeid
applied to a dereferenced pointer to a polymorphic type, the set consists of std::bad_typeid
. 6) If e is a new-expression with a non-constant array size, and the selected allocation function has a non-empty set of potential exceptions, the set consists of std::bad_array_new_length . | (since C++11) |
void f() throw(int); // f()'s set is "int" void g(); // g()'s set is the set of all types struct A { A(); }; // "new A"'s set is the set of all types struct B { B() noexcept; }; // "B()"'s set is empty struct D() { D() throw (double); }; // new D's set is the set of all types
All implicitly-declared member functions and inheriting constructors (since C++11)have exception specifications, selected as follows:
noexcept(false)
(since C++11). throw()
(until C++11)noexcept(true)
(since C++11). struct A { A(int = (A(5), 0)) noexcept; A(const A&) throw(); A(A&&) throw(); ~A() throw(X); }; struct B { B() throw(); B(const B&) = default; // exception specification is "noexcept(true)" B(B&&, int = (throw Y(), 0)) noexcept; ~B() throw(Y); }; int n = 7; struct D : public A, public B { // May throw an exception of a type that would match a handler of type // std::bad_array_new_length, but does not throw a bad allocation exception (void*) new (std::nothrow) int[n]; // D may have the following implicitly-declared members: // D::D() throw(X, std::bad_array_new_length); // D::D(const D&) noexcept(true); // D::D(D&&) throw(Y); // D::~D() throw(X, Y); };
Note: best be compiled in C++98 mode to avoid warnings. Incompatible with C++17 and newer revisions.
#include <cstdlib> #include <exception> #include <iostream> class X {}; class Y {}; class Z : public X {}; class W {}; void f() throw(X, Y) { bool n = false; if (n) throw X(); // OK, would call std::terminate() if (n) throw Z(); // also OK throw W(); // will call std::unexpected() } void handler() { std::cerr << "That was unexpected!\n"; // flush needed std::abort(); } int main() { std::set_unexpected(handler); f(); }
Output:
That was unexpected!
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 25 | C++98 | the behavior of assignment and initialization between pointers to members with different exception specifications was unspecified | apply the restriction for function pointers and references |
CWG 973 | C++98 | exception specification may contain functions types, but the corresponding function pointer conversion was not specified | specified |
CWG 1267 | C++11 | rvalue reference types were allowed in exception specifications | not allowed |
CWG 1351 | C++98 C++11 | default argument (C++98) and default member initializer (C++11) were ignored in implicit exception specification | made considered |
CWG 1777 | C++11 | throw(T...) was not a non-throwingspecification even if T is an empty pack | it is non-throwing if the pack is empty |
CWG 2191 | C++98 | the set of potential exceptions of a typeid expressionmight contain bad_typeid even if it cannot be thrown | contains bad_typeid only if it can be thrown |
noexcept specifier(C++11) | specifies whether a function could throw exceptions |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/language/except_spec