你这个问法可能不太对……首先不怎么建议问(不管别人还是自己)选 A 还是选 B 这种问题,因为答案很可能是 C ( std::optional 或者 std::expected ),也可能预设的选项会干扰别人的思路,而且很可能会得到一堆没怎么说清楚理由的个人偏好。
一个可能的一般性思路是如果不是很确定怎么解决一个问题的话,那我们可以尝试找个能同时解决多个问题的方案(一方面能交叉对比排除掉一些错误答案,一方面一个模式如果是有效的话很难相信只在一个地方起作用)。比如它最好能同时锻炼某种学习 C++时需要的独立整蛊能力和提供能迁移到其他语言中的知识。所以或许可以尝试一下下面这套办法:
1. 先找找最新的与 error handling 相关的 proposal ,然后发现最近的进展差不多在
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0323r10.html 里面( std::expected ),花几分钟读完 motivation ,就脱离了很多人长时间里陷入的那种凭感觉选一种方式但也说不清为什么的阶段了。继续读需要先看看里面提到的 std::optional 那篇(以及后续的改进
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0798r8.html 与 std::expected 那篇里面提到的类似 proposal ),如果感觉读着很爽就直接顺着往下看。
2. 由于 C++23 还不知道什么时候能用上,使用 std::expected 的例子可能不太多,纯读 proposal 如果感觉无聊 /读不下去的话可以拿对 std::optional 的讨论与使用凑合一下(比如
https://devblogs.microsoft.com/cppblog/stdoptional-how-when-and-why/,或者 CppCon 里面应该有一些相关的 talk ,由于一个话题很可能会讲好几次所以挑个喜欢的跳着看吧)然后假装 std::optional<T>就是 std::expected<T, nullopt_t>来辅助理解 std::expected 。另一个选择是看一下 Rust 里面和 std::expected<T,E>类似的处理方式 Result<T,E>是怎么设计和使用的(
https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html 和
https://doc.rust-lang.org/rust-by-example/error.html )
3. 以上文档可能还有一些没直接说清楚的问题(比如 pair<bool, T>和 optional<T>不考虑后者在不必要时能不初始化 T 等问题之后好像有点像,或者除了感觉不爽以外还能用什么借口拒绝 tuple ,或者为啥那 proposal 要用 monadic 这么神经病的词,或者什么别的在你心里像是长了条猪尾巴一样乱晃的问题),这个时候看一些抽象一点却又没那么抽象的东西,比如 type system 相关的材料,会比较舒服。关键字大概是 algebraic data type, product/sum type 和 monad 。一个比较具体但不够深入的选择是 Programming with Types: Examples in TypeScript 的第 3 章和第 11 章,当然如果不喜欢 Typescript 或者嫌它没讲清楚(的确如此)也有大把的其他饲料可以选择就是了。