Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/except spec"

From cppreference.com
< cpp‎ | language
(2047. Coordinating “throws anything” specifications)
Line 24: Line 24:
 
If the function throws an exception of the type not listed in its exception specification, the function {{lc|std::unexpected}} is called. The default function calls {{lc|std::terminate}}, but it may be replaced by a user-provided function (via {{lc|std::set_unexpected}}) which may call {{lc|std::terminate}} or throw an exception. If the exception thrown from {{lc|std::unexpected}} is accepted by the exception specification, stack unwinding continues as usual. If it isn't, but {{lc|std::bad_exception}} is allowed by the exception specification, {{lc|std::bad_exception}} is thrown. Otherwise, {{lc|std::terminate}} is called.
 
If the function throws an exception of the type not listed in its exception specification, the function {{lc|std::unexpected}} is called. The default function calls {{lc|std::terminate}}, but it may be replaced by a user-provided function (via {{lc|std::set_unexpected}}) which may call {{lc|std::terminate}} or throw an exception. If the exception thrown from {{lc|std::unexpected}} is accepted by the exception specification, stack unwinding continues as usual. If it isn't, but {{lc|std::bad_exception}} is allowed by the exception specification, {{lc|std::bad_exception}} is thrown. Otherwise, {{lc|std::terminate}} is called.
  
{{rev begin}}
+
===Potential exceptions{{mark|since=c++17}}===
{{rev|since=c++17|
+
===Potential exceptions===
+
 
Each function {{tt|f}}, pointer to function {{tt|fp}}, and pointer to member function {{tt|mfp}} 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:
 
Each function {{tt|f}}, pointer to function {{tt|fp}}, and pointer to member function {{tt|mfp}} 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:
 
@1@ If the declaration of {{tt|f}}, {{tt|fp}}, or {{tt|mfp}} uses {{tt|throw()}}{{mark deprecated}} or {{rlp|noexcept}}, the set is empty.
 
@1@ If the declaration of {{tt|f}}, {{tt|fp}}, or {{tt|mfp}} uses {{tt|throw()}}{{mark deprecated}} or {{rlp|noexcept}}, the set is empty.

Revision as of 20:56, 21 October 2016

 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
Exceptions
try block
Throwing exceptions
Handling exceptions
Exception specification
    noexcept specification (C++11)
    dynamic specification (until C++17*)
noexcept operator (C++11)
 

Lists the exceptions that a function might directly or indirectly throw.

Contents

Syntax

throw(typeid, typeid, ...) (deprecated)

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 exceptions({{{1}}})

Each function f, pointer to function fp, and pointer to member function mfp 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:

1) If the declaration of f, fp, or mfp uses throw()(deprecated) or noexcept, the set is empty.
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 specification
3) 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 e has a set of potential exceptions, defined as follows:

1) If e is a core constant expression, the set is empty
2) Otherwise, the set 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:
1) If 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.
  • 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
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)
4) If e is a dynamic_cast to a reference to a polymorphic type, the set consists of std::bad_cast
5) If e is a typeid applied to a polymorphic glvalue, the set consists of std::bad_typeid
6) If e is a new-expression with a non-constant size, the set consists of std::bad_array_new_length
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:

  • If the set of potential exceptions is the set of all types, the implicit exception specification is noexcept(false).
  • Otherwise, If the set of potential exceptions is not empty, the implicit exception specification lists every type from the set
  • Otherwise, the implicit exception specification is noexcept(true) and the function type is "noexcept function"
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)) throw(Y) 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);
};

}} </table>

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

See also