dynamic exception specification
动态异常规范
列出函数可能直接或间接抛出的异常。
句法
throw( ) | | (deprecated in c++11) |
---|---|---|
throw(typeid, typeid, ...) | | (deprecated in C++11)(until C++17) |
1) Non-throwing dynamic exception specification | (until C++17) |
---|---|
1) Same as noexcept(true) | (since C++17) |
2%29显式动态异常规范
此规范只能出现在函数、变量或非静态数据成员(其类型为函数类型、指向函数类型的指针、函数类型的引用、成员函数类型的指针)的顶级%28的函数声明器或函数声明器上,直到C++17%29声明器。它可能出现在参数的声明符或返回类型的声明器上。
二次
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
二次
解释
如果函数是用类型声明的T
在其异常规范中列出的函数可能引发该类型的异常或由此派生的类型。
不完全类型、指针或对cv以外的不完整类型的引用。void*
,并且在异常规范中不允许使用rvalue引用类型。如果使用数组和函数类型,则调整为相应的指针类型。参数包自C++11%29开始允许%28。
如果函数抛出其异常规范中未列出的类型的异常,则函数std::unexpected
叫做。默认函数调用std::terminate
,但是它可以被用户提供的函数%28via替换。std::set_unexpected
%29可调用std::terminate
或者抛出一个异常。如果抛出的异常std::unexpected
异常规范接受,则堆栈展开将继续如常进行。如果是%27T,但是std::bad_exception
是异常规范允许的,std::bad_exception
被扔了。否则,std::terminate
叫做。
Potential exceptions 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) intn; // 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) |
---|
- 该函数由id表达式%28直接命名,或作为成员访问或指针到成员访问表达式%29的一部分,命名函数的一组潜在异常将添加到列表中。
- 如果该函数由no以外函数的表达式或指向no以外函数的类型指针的表达式命名,则该集合为空。
- 否则,集合是所有类型的集合。
2%29e
调用一个函数隐式%28 it%27 s为运算符表达式,且运算符重载,则为新表达式而分配函数是重载的,或者是一个完整的表达式,临时的析构函数被称为%29%29,那么这个集合就是该函数的集合。3%29e
是抛出,则该集合是将由其操作数初始化的异常,或者是用于重新抛出抛出表达式%28的所有类型的集合,如果没有操作数%29 4%29,则为e
是动态[医]铸造对于多态类型的引用,集合由std::bad_cast
5%29e
是类型应用于多态极值,该集合由std::bad_typeid
6%29e
是新表达式具有非常量大小的集合由std::bad_array_new_length
空f%28%29抛出%28 int%29;//f%28%29%27s集是“int”空G%28%29;//g%28%29%27 s集是所有类型结构A{A%28%29;};///“新A”%27s集是所有类型结构B{B%28%29 Noo除外的集合;//“B%28%29”%27s集为空结构D%28%29{D%28%29抛出%28双%29};//新D%27s集是所有类型的集合
所有隐式声明的成员函数%28和继承构造函数%29都有异常规范,选择如下:
- 如果潜在异常集是所有类型的集合,则隐式异常规范为
noexcept(false)
...
- 否则,如果潜在异常集不是空的,则隐式异常规范将列出集合中的每个类型。
- 否则,隐式异常规范是
noexcept(true)
函数类型为“除函数外”。
结构A{A%28int=%28A%285%29,0%29%29 no;A%28 const A&%29掷出%28%29;A%28A&%29掷出%28%29;~A%28%29掷出%28X%29;};结构B{B%28%29抛出%28%29;B%28 const B&%29=默认;//异常规格是“no除%28true%29 B%28B%28B&&,int=%28掷Y%28%29,0%29%29扔%28Y%29 noout;~B%28%29抛出%28Y%29;};INT n=7;结构D:public A,public B{int%2AP=新的%28 std::noput%29 intn//D有以下隐式声明的成员://D::d%28%29引发%28X,std::坏[医]列阵[医]新[医]长度%29;//D::d%28 const D&%29 no,除%28true%29;//D::d%28D&%29掷%28Y%29;//D:~D%28%29 pt%28X,Y%29;};
%28自C++17%29
例
二次
#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(
}
二次
产出:
二次
That was unexpected
二次
另见
noexcept
说明符
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。