Difference between revisions of "cpp/language/except spec"
(Undo revision 101993 by 91.210.252.147 (talk)) |
(Remove incorrect claim that constant expressions are implicitly considered non-throwing in C++17. (This was removed by P0003R1 and CWG has even affirmed they want to treat the removal as a DR.)) |
||
Line 44: | Line 44: | ||
Note: for implicitly-declared special member functions (constructors, assignment operators, and destructors) and for the inheriting constructors, 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) | Note: for implicitly-declared special member functions (constructors, assignment operators, and destructors) and for the inheriting constructors, 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 {{tt|e}} has a ''set of potential exceptions'', | + | Each expression {{tt|e}} has a ''set of potential exceptions'', which is the union of the sets of potential exceptions of all immediate subexpressions of {{tt|e}} (including {{rlp|default arguments|default argument expressions}}), combined with another set that depends on the form of {{tt|e}}, as follows: |
− | + | @1@ If {{tt|e}} is a function call expression, and | |
− | + | ||
− | + | ||
* the function is named by an id-expression (either directly or as part of member access or pointer-to-member access expression), the set of potential exceptions of the named function is added to the list. | * the function is named by an id-expression (either directly or as part of member access or pointer-to-member access expression), the set of potential exceptions of the named function is added to the list. | ||
* if the function is named by an expression of type noexcept function or by an expression of type pointer to noexcept function, the set is empty | * if the function is named by an expression of type noexcept function or by an expression of type pointer to noexcept function, the set is empty | ||
* otherwise, the set is the set of all types | * otherwise, the set is the set of all types | ||
− | + | @2@ If {{tt|e}} calls a function implicitly (it's an operator expression and the operator is overloaded, it is a {{rlp|new|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. | |
− | + | @3@ If {{tt|e}} is a {{rlp|throw|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) | |
− | + | @4@ If {{tt|e}} is a {{rlp|dynamic_cast}} to a reference to a polymorphic type, the set consists of {{lc|std::bad_cast}} | |
− | + | @5@ If {{tt|e}} is a {{rlp|typeid}} applied to a polymorphic glvalue, the set consists of {{lc|std::bad_typeid}} | |
− | + | @6@ If {{tt|e}} is a {{rlp|new|new-expression}} with a non-constant size, the set consists of {{lc|std::bad_array_new_length}} | |
{{source|1= | {{source|1= |
Revision as of 10:54, 19 July 2018
Lists the exceptions that a function might directly or indirectly throw.
Contents |
Syntax
throw( )
|
(1) | (deprecated in C++11) | |||||||
throw( typeid, typeid, ...)
|
(2) | (deprecated in C++11)(until C++17) | |||||||
1) Non-throwing dynamic exception specification
|
(until C++17) |
1) Same as noexcept(true)
|
(since C++17) |
This specification may appear only on lambda-declarator or on a function declarator that is the top-level(until C++17) declarator of a function, variable, or non-static data member, whose type is a function type, a pointer to function type, a reference to function type, a pointer to member function type. It may appear on the declarator of a parameter or on the declarator of a return type.
void f() throw(int); // OK: function declaration void (*fp)() 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
Explanation
If a function is declared with type T
listed in its 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 are not allowed in the exception specification. Array and function types, if used, are adjusted to corresponding pointer types. parameter packs are allowed(since C++11).
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.
Potential exceptionsEach function 2) Otherwise, if the declaration of
f , fp , or mfp uses a dynamic exception specification(deprecated), the set consists of the types listed in that specification3) Otherwise, the set is the set of all types
Note: for implicitly-declared special member functions (constructors, assignment operators, and destructors) and for the inheriting constructors, 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 1) If
e is a function call expression, and
2) If
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.3) If
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)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) have exception specifications, selected as follows:
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 { int * p = new (std::nothrow) int[n]; // D has 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); }; |
(since C++17) |
Example
#include <iostream> #include <exception> #include <cstdlib> class X {}; class Y {}; class Z : public X {}; class W {}; void f() throw(X, Y) { int n = 0; if (n) throw X(); // OK if (n) throw Z(); // also OK throw W(); // will call std::unexpected() } int main() { std::set_unexpected([]{ std::cout << "That was unexpected" << std::endl; // flush needed std::abort(); }); f(); }
Output:
That was unexpected