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 typesAll 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_typeidonly 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