Outcome 2.2 库
版权所有 © 2014-2024 Niall Douglas 及其他
根据 Boost 软件许可,版本 1.0 分发。(请参阅随附文件 LICENSE_1_0.txt 或访问 https://boost.ac.cn/LICENSE_1_0.txt 副本)
简介
Outcome 是一组用于报告和处理函数失败的工具,适用于直接使用 C++ 异常处理不合适的场合。 这些场合包括
有些程序或其部分在编译时禁用了异常;
程序的部分有很多分支依赖于失败的类型,在这种情况下,if 语句比 try-catch 块更清晰;
存在硬性要求,即执行失败路径的成本不应高于执行成功路径的成本;
在某些情况下,例如在
filesystem
库中,是否应远程处理失败(使用 C++ 异常抛出),或者是否应在函数内部本地处理失败,这无法在函数内部决定,而需要由调用者决定,并且在后一种情况下,出于上述原因,抛出 C++ 异常是不可取的;程序/框架的某些部分本身实现了异常处理,并且不希望使用异常来跨线程、任务、纤程等传播失败报告;
需要通过未实现异常抛出安全性的层来传播异常;
存在外部要求(例如公司范围内的政策),即失败处理路径在代码中显式指示。
与 C 代码互操作很重要,而无需诉诸 C++ 异常包装器垫片。
您的主要 C 代码库需要类似异常的错误处理,并且 C 中可用的 Outcome 功能子集足以满足您的需求。
Outcome 通过从函数返回一种特殊类型来处理失败,这种类型能够存储成功计算的值(或 void
),或有关失败的信息。 Outcome 还附带一组用于处理此类类型的习惯用法。
已特别注意确保 Outcome 对构建时间的影响尽可能低,从而使其适用于真正大型代码库的全局标头中使用。 存储布局是有保证的,并且与 result<T, E>
1 的 C 兼容,从而使基于 Outcome 的代码具有长期 ABI 稳定性。
Outcome 中完全确定性的 all-noexcept
C++ 协程支持特别强大,我们提供 Outcome 优化的 eager<T, Executor = void>/atomic_eager<T, Executor = void>
, lazy<T, Executor = void>/atomic_lazy<T, Executor = void>
和 generator<T, Executor = void>
awaitables,它们适用于任何用户类型。
示例用法 (C++)
Outcome 库中的主要工作组件是 result<T>
:它表示类型 T
的成功计算值,或表示失败原因的 std::error_code
/boost::system::error_code
2。 您在函数的返回类型中使用它
outcome::result<string> data_from_file(string_view path) noexcept;
可以手动检查状态
if (outcome::result<string> rslt = data_from_file("config.cfg"))
use_string(rslt.value()); // returns string
else
throw LibError{rslt.error(), "config.cfg"}; // returns error_code
或者,如果此函数在另一个也返回 result<T>
的函数中调用,则可以使用专用控制语句
outcome::result<int> process(const string& content) noexcept;
outcome::result<int> int_from_file(string_view path) noexcept
{
BOOST_OUTCOME_TRY(auto str, data_from_file(path));
// if control gets here data_from_file() has succeeded
return process(str); // decltype(str) == string
}
BOOST_OUTCOME_TRY
是一个控制语句。 如果返回的 result<T>
对象包含错误信息,则封闭函数会立即返回,并返回包含相同失败信息的 result<U>
; 否则,类型为 T
的自动对象在作用域内可用。
示例用法 (C)
等效于 C++ API:BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM(ident, T)
声明 C 类型,此后 BOOST_OUTCOME_C_RESULT_SYSTEM(ident)
引用它。 您在函数的返回类型中使用它
BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM(result_string, const char *)
BOOST_OUTCOME_C_RESULT_SYSTEM(result_string) data_from_file(const char *path);
可以手动检查状态
BOOST_OUTCOME_C_RESULT_SYSTEM(result_string) rslt = data_from_file("config.cfg");
if(BOOST_OUTCOME_C_RESULT_HAS_VALUE(rslt))
use_string(rslt.value); // returns string
else
fprintf(stderr, "%s\n", outcome_status_code_message(&rslt.error));
或者,如果此函数在另一个也返回 BOOST_OUTCOME_C_RESULT_SYSTEM(ident)
的函数中调用,则可以使用专用控制语句
BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM(result_int, int)
BOOST_OUTCOME_C_RESULT_SYSTEM(result_int) process(const char *content);
BOOST_OUTCOME_C_RESULT_SYSTEM(result_int) int_from_file(const char *path)
{
BOOST_OUTCOME_C_RESULT_SYSTEM_TRY(const char *str, result_int, /* cleanup on fail */, data_from_file(path));
// if control gets here data_from_file() has succeeded
return process(str); // decltype(str) == string
}
C Result 保证其布局与其 C++ 等效项相同。 提供了便捷的转换函数,但您也可以进行 reinterpret_cast。