1. 概述
本文原文地址: concepts/how-optional-and-error-values-are-returned-in-iceoryx.md
本文介绍如何在 iceoryx 中返回可选值和错误值
iceoryx 的许多 C++ API 部分遵循函数式编程的方法,允许用户指定处理可能情况的函数,例如在接收到数据时应该发生什么。
这非常灵活,但要求使用单子类型 iox::expected
和 iox::optional
,我们将在以下章节中介绍这两者。
2. 可选值
iox::optional<T>
类型用于表示可能有也可能没有某种特定类型 T
的值。这本质上是函数式编程中的“也许 单子”。
iox::optional
的行为类似于 std::optional
,只是它在 std::optional
会抛出异常或表现为未定义行为的地方会终止应用程序。
假设我们有一个可选值(通常是某些计算的结果)
optional<int> result = someComputation();
我们可以使用以下代码检查其值
if(result.has_value())
{
auto value = result.value();
// 使用值进行操作
}
else
{
// 处理没有值的情况
}
获取值的简写方式是
auto value = *result;
!!! 注意
如果没有值时访问它会终止应用程序,因此必须事先检查。
我们可以通过提供处理两种情况的函数来使用函数式方法实现相同的效果。
result.and_then([](int& value) { /* 使用值进行操作*/ })
.or_else([]() { /* 处理没有值的情况*/ });
注意,我们通过引用获取值,因此如果需要复制,必须在我们传递的 lambda 表达式 或函数中显式创建。
可选值可以直接从值初始化
optional<int> result = 73;
result = 37;
如果可选值是默认初始化的,则会自动设置为其 iox::nullopt_t
类型的空值。这也可以通过使用常量 iox::nullopt
直接完成
result = iox::nullopt;
有关可用函数的完整列表,请参见 optional.hpp
。
3. 期望值
iox::expected<T, E>
通过允许另一个类型 E
的值来泛化 iox::optional
,而不是完全没有值,即它包含类型 T
或 E
的值。这样,expected
是“或单子”的特例。它通常用于传递类型 T
的值或可能发生的错误,即 E
是错误类型。
有关如何用于错误处理的更多信息,请参见 error-handling.md。
假设我们有 E
作为错误类型,那么我们可以创建一个值
iox::expected<int, E> result(iox::ok(73));
并使用值或处理潜在的错误
if (result.has_value())
{
auto value = result.value();
// 使用值进行操作
}
else
{
auto error = result.error();
// 处理错误
}
如果我们需要一个错误值,可以设置
result = iox::err(errorCode);
这假设 E
可以从 errorCode
构造。
我们也可以像这样使用函数式方法:
auto handleValue = [](int& value) { /* 使用值进行操作*/ };
auto handleError = [](E& value) { /* 处理错误*/ };
result.and_then(handleValue).or_else(handleError);
还有更多便利函数,如 value_or
,它提供值或用户指定的替代值。这些函数可以在 expected.hpp
中找到。
请注意,当我们移动一个 expected
时,源对象会包含一个已移动的 T
或 E
,这取决于移动前的内容。这反映了将内容从 iox::expected
中移出的行为,例如 auto foo = std::move(bar.value());
,其中 bar
是一个 iox::expected
。像所有对象一样,T
和 E
必须在移动后保持良好的状态。