You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将std::expected作为输入参数是否属于反模式?

关于std::expected作为函数参数的设计疑问

先贴出你提到的代码片段:

using ThingName = std::string;
using Error = std::string;
std::vector<Thing> make_things(std::expected<std::vector<ThingName>, Error> names) {
  ...
}

开发者意图猜测

  • 大概率是想简化调用方代码:让调用方不用提前处理expected的错误分支,直接把结果传给make_things,由它兜底处理错误。
  • 也可能是对std::expected的设计目的理解偏差——std::expected本质是用来传递函数执行的成功/失败结果,而非作为“带错误的输入参数”使用。

函数的实际契约

从代码实现(收到错误就抛异常)来看,这个函数的契约是:

我需要一个合法的ThingName列表来生成Thing集合;如果传入的是错误信息,我会抛出异常终止当前流程,不会返回有效结果。

但这个契约和std::expected的设计初衷冲突——std::expected本就是为了避免隐式异常,让错误处理显式化,这种写法相当于绕回了异常式错误处理的老路。

是不是反模式?

没错,这属于典型的反模式,原因如下:

  • 浪费了std::expected的核心价值:它的存在就是为了让调用方显式选择错误处理方式(比如降级处理、重试、返回默认值),而非把错误隐式转成异常。
  • 违背“错误尽早处理”原则:错误应该在产生的上游就被处理,而非传到下游核心逻辑里再崩溃。如果make_things必须依赖合法输入,参数就该直接用std::vector<ThingName>,让调用方保证输入合法,或者在调用前处理错误。

有没有合理的使用场景?

几乎没有,但硬要找的话,可能存在两种过渡性场景:

  • 逻辑错误兜底:如果上游的expected错误本就属于“不可能发生”的逻辑错误(比如已经在其他地方做了严格校验),此时make_things收到错误就抛异常,相当于断言,用来捕获程序逻辑漏洞。
  • 兼容旧代码:如果项目正在从异常式错误处理迁移到std::expected,这个函数作为中间层,把expected的错误转成异常适配原有依赖异常的代码流程,但这只是临时方案,最终还是要统一错误处理风格。

内容的提问来源于stack exchange,提问作者Eugene K.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:12:38