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

如何用模板推导指南让std::expected支持return {1,2}式返回?

问题分析与解决方案

先根据你的描述还原核心代码场景:

#include <expected>
#include <string>

struct s {
    int a;
    int b;
};

// 你希望编译通过的目标函数
std::expected<s, std::string> Func0() {
    return {1, 2}; // 当前编译失败
}

// 双层大括号可正常编译
std::expected<s, std::string> Func1() {
    return {{1, 2}};
}

// 先构造s对象可正常编译
std::expected<s, std::string> Func2() {
    return s{1, 2};
}

为什么return {1,2}编译失败?

直接返回{1,2}时,编译器会尝试用两个int值直接构造std::expected<s, std::string>,但std::expected没有提供接受两个int参数的构造函数。而双层大括号{{1,2}}的逻辑是:内层大括号先构造s对象,再将这个s传给std::expected的成功值构造函数(接受T&&的模板构造函数),因此可以编译通过。

推导指南在这里不可行

你尝试的推导指南expected(int, int) -> expected<int, int>;完全不匹配需求——它是用来推导构造std::expected<int, int>的场景,和你要的std::expected<s, std::string>无关。更关键的是:Func0的返回类型已经明确是std::expected<s, std::string>,不存在类模板参数推导(CTAD)的过程,推导指南的作用是在你未显式指定类模板参数时(比如直接写expected e{...};)推导模板类型,无法解决返回列表的构造匹配问题。

可行的解决方案

方案1:保留显式构造s的写法(即Func2的方式)

这种写法清晰直接,不需要额外代码,唯一代价是多写一个s类型名。

方案2:编写make_expected辅助函数

类似标准库的make_pair/make_shared,通过参数转发自动构造目标类型并包装成std::expected:

#include <utility> // 用于std::forward

template<class T, class... Args>
constexpr std::expected<T, std::string> make_expected(Args&&... args) {
    return std::expected<T, std::string>(T{std::forward<Args>(args)...});
}

// 使用方式
std::expected<s, std::string> Func0() {
    return make_expected<s>(1, 2);
}

如果需要支持自定义错误类型,可以把错误类型也作为模板参数:

template<class T, class E = std::string, class... Args>
constexpr std::expected<T, E> make_expected(Args&&... args) {
    return std::expected<T, E>(T{std::forward<Args>(args)...});
}

内容的提问来源于stack exchange,提问作者Philippe Sanche

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:13:28