std::experimental:: scope_success
|
定义于头文件
<experimental/scope>
|
||
|
template
<
class
EF
>
class scope_success ; |
(库基础技术规范 v3) | |
类模板
scope_success
是一种通用作用域守卫,旨在当作用域正常退出时调用其退出函数。
scope_success
不满足
可复制构造
、
可复制赋值
或
可移动赋值
的要求,但如果
EF
满足特定条件时,它可能满足
可移动构造
的要求,这允许将
scope_success
包装到另一个对象中。
一个
scope_success
可以是激活状态(即在析构时调用其退出函数)或非激活状态(即在析构时不执行任何操作)。当从退出函数构造完成后,
scope_success
处于激活状态。
一个
scope_success
可以通过手动调用其
release()
方法或自动(通过移动构造函数)变为非活动状态。通过使用另一个非活动的
scope_success
进行初始化也可以获得非活动的
scope_success
。一旦
scope_success
变为非活动状态,就无法再次激活。
一个
scope_success
实际上持有一个
EF
和一个
bool
标志(指示其是否处于活动状态),同时附带一个未捕获异常计数器,用于检测析构函数是否在栈展开期间被调用。
目录 |
模板参数
| EF | - | 存储的退出函数类型 |
| 类型要求 | ||
-
EF
应为以下类型之一:
|
||
|
-
|
||
成员函数
构造新的
scope_success
(公开成员函数) |
|
若
scope_success
为激活状态,则在作用域正常退出时调用退出函数,然后销毁
scope_success
(公开成员函数) |
|
|
operator=
[deleted]
|
scope_success
不可赋值
(公开成员函数) |
修改器 |
|
使
scope_success
转为非激活状态
(公开成员函数) |
|
推导指引
注解
构造动态存储期的
scope_success
可能导致未预期行为。
在不同线程中创建的
scope_success
对象之间进行构造操作可能导致未定义行为,因为在析构过程中可能会比较不同线程中获取的未捕获异常计数。
如果存储在
scope_success
对象中的
EF
引用其定义函数中的局部变量(例如通过引用捕获该变量的 lambda),且该变量在该函数中作为返回操作数使用,那么当
scope_success
的析构函数执行并调用退出函数时,该变量可能已被返回。这可能导致意外行为。
示例
#include <iostream> #include <cstdlib> #include <string_view> #include <experimental/scope> void print_exit_status(std::string_view name, bool exit_status, bool did_throw) { std::cout << name << ":\n"; std::cout << " 是否抛出异常 " << (did_throw ? "是" : "否") << "\n"; std::cout << " 退出状态 " << (exit_status ? "已完成" : "待处理") << "\n\n"; } // 随机抛出异常(50%概率) void maybe_throw() { if (std::rand() >= RAND_MAX / 2) throw std::exception{}; } int main() { bool exit_status{false}, did_throw{false}; // 在"作用域结束"时手动处理 try { maybe_throw(); exit_status = true; } catch (...) { did_throw = true; } print_exit_status("手动处理", exit_status, did_throw); // 使用 scope_exit:在作用域退出时运行(无论成功或异常) exit_status = did_throw = false; try { auto guard = std::experimental::scope_exit{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_exit", exit_status, did_throw); // 使用 scope_fail:仅在发生异常时运行 exit_status = did_throw = false; try { auto guard = std::experimental::scope_fail{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_fail", exit_status, did_throw); // 使用 scope_success:仅在没有异常发生时运行 exit_status = did_throw = false; try { auto guard = std::experimental::scope_success{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_success", exit_status, did_throw); }
输出:
手动处理: 是否抛出异常 是 退出状态 待处理 scope_exit: 是否抛出异常 否 退出状态 已完成 scope_fail: 是否抛出异常 是 退出状态 已完成 scope_success: 是否抛出异常 是 退出状态 待处理
参阅
|
包装函数对象并在退出作用域时调用它
(类模板) |
|
|
包装函数对象并在通过异常退出作用域时调用它
(类模板) |
|
|
(C++11)
|
unique_ptr
的默认删除器
(类模板) |