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

如何用C++23的std::expected及transform_error处理stoi抛出的错误?

用std::expected实现无try-catch的字符串转整数错误处理

先直接说结论:原生std::stoi没法直接配合std::expected实现无try-catch的错误处理——因为std::stoi本身是靠抛出异常报告错误的,而std::expected是基于返回值的「铁路式」错误处理模型。要达成你要的效果,得先封装一个不抛异常的字符串转整数函数,再结合std::expected和transform_error来处理错误。

具体实现步骤

1. 封装非抛出式的字符串转整数函数

C++17引入的std::from_chars是无异常的字符串转数值工具,它返回std::from_chars_result,其中包含转换是否成功的状态(ec字段,类型为std::error_code)。我们可以基于它封装一个返回std::expected<int, std::error_code>的函数:

#include <string>
#include <expected>
#include <charconv>
#include <system_error>

std::expected<int, std::error_code> stoi_noexcept(std::string_view s) {
    int value;
    auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), value);
    if (ec == std::errc()) {
        // 转换成功,返回整数值
        return value;
    } else {
        // 转换失败,返回错误码
        return std::unexpected(ec);
    }
}

2. 用std::expected和transform_error处理错误

有了非抛出式的函数后,就可以用std::expected的链式调用(包括transform_error)实现铁路式错误处理,全程不需要try-catch:

#include <iostream>

void handleInput(char* argv[]) {
    stoi_noexcept(argv[1])
        // 把error_code转换成可读性高的错误信息字符串
        .transform_error([](std::error_code ec) -> std::string {
            if (ec == std::errc::invalid_argument) {
                return "invalid argument: 无法将输入转换为整数";
            } else if (ec == std::errc::result_out_of_range) {
                return "out of range: 输入值超出整数范围";
            } else {
                return "unknown error: " + ec.message();
            }
        })
        // 处理转换成功的逻辑
        .and_then([](int value) -> std::expected<void, std::string> {
            std::cout << "转换成功,值为: " << value << std::endl;
            return {};
        })
        // 处理错误逻辑
        .or_else([](std::string err_msg) -> std::expected<void, std::string> {
            std::cerr << err_msg << std::endl;
            return std::unexpected(std::move(err_msg));
        });
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "请提供一个字符串参数" << std::endl;
        return 1;
    }
    handleInput(argv);
    return 0;
}

关键说明

  • transform_error的核心作用是将std::expected中的错误类型转换为更适合后续处理的类型(这里从std::error_code转为std::string),实现错误信息的统一格式化。
  • 之所以不能直接用原生std::stoi,是因为它的错误报告机制是抛出异常而非返回错误状态。如果硬要结合std::expected,必须先用try-catch捕获异常再塞进std::unexpected,这就无法避免try-catch块,不符合你的需求。
  • std::from_chars是专门为错误处理优化的工具,它的设计完全基于返回值报告状态,完美匹配std::expected的使用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:33:27