C++ 相当于 Rust 的 Result<T, E> 类型?

C++ equivalent of Rust's Result<T, E> type?

我喜欢在我的 C++ 代码中使用 std::experimental::optional,但问题是 value_or 要求默认值与可选值的类型相同。

当我想要一个包含 int 或包含错误消息的可选值时,这不太适用。

我想我可以使用一个具有布尔值的联合结构来指示该值是否存在或它是一个错误,但如果 C++ 有一个像 Rust 这样的 Result<T, E> 类型肯定会很好。

有这种类型的吗?为什么 Boost 没有实现它?

Result 确实比 Option 有用得多,Boost 的人肯定知道它的存在。也许我会去阅读 Rust 实现,然后将其复制到 C++?

例如:

// Function either returns a file descriptor for a listening socket or fails
// and returns a nullopt value.
// My issue: error messages are distributed via perror.
std::experimental::optional<int> get_tcp_listener(const char *ip_and_port);
// You can use value_or to handle error, but the error message isn't included!
// I have to write my own error logger that is contained within
// get_tcp_listener. I would really appreciate if it returned the error
// message on failure, rather than an error value.
int fd = get_tcp_listener("127.0.0.1:9123").value_or(-1);
// Rust has a type which does what I'm talking about:
let fd = match get_tcp_listener("127.0.0.1:9123") {
    Ok(fd) => fd,
    Err(msg) => { log_error(msg); return; },
}

optional 按照设计要么包含某种类型的值,要么什么都不包含。

您可能正在寻找类似 Boost::Variant 的内容。

这还不是标准库的一部分,尽管最终可能会有类似的东西。

您正在寻找的正是 Alexandrescu 的预期。我建议听他的演讲以深入了解:https://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C。他实际上是一行一行的实现,你可以很容易的自己写出来,然后用好。

Variant 是一种更通用的工具,它可以被强制执行您想要的操作,但您最好使用 expected。

optional<T>T和虚无(nullopt_t)的非对称类型安全联合。你可以查询它是否有 Texplicit operator bool,并用一元 * 得到 T。不对称意味着可选 "prefers" 是 T,这就是为什么不合格的操作(如 * 或运算符 bool)引用其 Tness。

variant<A,B,C> from paper n4218ABC(等)的对称类型安全联合。 boost::variant 一直在忙,std::experimental::variant 几乎 一直在忙。

由于是对称的,一元*到return没有唯一类型,explicit operator bool也没什么意思,所以都不支持。

相反,您必须访问它,或查询它的特定类型。

std::experimental::expected<E, T> from paper n4015 是一个非对称类型安全联合。它要么是 T,要么是 E。但是像optional一样,它"prefers"是一个T;它有一个 explicit operator bool 告诉你它是否是 T,一元 * 得到 T.

从某种意义上说,expected<E,T> 是一个 optional<T>,但是当它为空而不是浪费 space 时,它存储了一个 E,您可以查询它。

Result<T,E> 似乎接近 expected<E,T>(请注意,从 n4015 开始,与 Result 相比,参数的顺序被交换了)。

如果不仅涉及升压,您还可以使用 result。这是一个很好的单头容器。