为何std::expected<void, Error>不支持monadic操作?
你遇到的问题其实不是C++标准的std::expected实现不完整,而是对void特化的expected的monadic操作(and_then/or_else)的使用规则理解有误——and_then和or_else要求传入的闭包必须返回另一个std::expected类型(可以是void特化的版本),而不是直接返回void。
我们先拆解你的代码问题:
std::expected<void, Error> fun (int); fun (19).and_then ([]() { doSomething(); }).or_else ([] (Error e) { std::println ("Uh oh error.."); });
这里的and_then闭包[]() { doSomething(); }返回的是void,但and_then的设计逻辑是接收一个返回std::expected<...>的可调用对象——它需要延续expected的链式状态传递,直接返回void会打断这个状态链,所以触发了编译器的静态断言错误。
你看到的错误信息static assertion failed: std::__expected::__is_expected<void> evaluates to false就是最直接的提示:编译器期望闭包返回一个expected类型,但你给出的是void,完全不符合要求。
修正后的代码示例
要让这段代码正常工作,你需要让and_then和or_else的闭包都返回std::expected<void, Error>(或者兼容的expected类型),维持状态链的传递:
#include <expected> #include <print> enum class Error { OperationFailed }; std::expected<void, Error> fun(int val) { if (val == 19) return {}; // 成功:返回void特化的expected return std::unexpected(Error::OperationFailed); } void doSomething() { std::println("Executing doSomething..."); } int main() { fun(19) .and_then([]() -> std::expected<void, Error> { doSomething(); // 返回void特化的expected,表示当前步骤成功 return {}; }) .or_else([](Error e) -> std::expected<void, Error> { std::println("Uh oh error encountered.."); // 可选:继续传递错误,或返回成功终止链 return std::unexpected(e); }); return 0; }
设计逻辑的本质
std::expected的monadic操作核心是链式状态传递:每个链式调用都需要返回一个expected来表示当前步骤的成功/失败状态,这样后续的调用才能基于这个状态继续执行。
哪怕是void特化的expected,它依然代表“成功无返回值”或“失败带错误”的状态,所以monadic操作要求闭包返回expected来维持这个状态链,而不是直接返回void打断链条。这不是标准的遗漏,而是monadic操作的本质要求——它要确保每一步都能把状态传递下去,而不是中途“断链”。
备注:内容来源于stack exchange,提问作者David

