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

如何编写可容纳不同强类型枚举错误码的C++错误结构体?

保留错误码类型信息的通用错误结构体实现

这确实是个很实际的需求——把强类型枚举直接转成int存储,虽然简单,但会丢失类型上下文,后续做错误匹配、日志输出或者调试时都会很不方便。下面给你两种靠谱的实现思路,你可以根据自己的场景选择:

方案一:用std::variant存储多类型错误码(推荐)

C++17引入的std::variant天生适合这种需要存储多种类型但保留原始类型信息的场景。我们可以把错误码定义为一个能容纳int和各种强枚举的variant,同时搭配错误消息:

#include <string>
#include <variant>
#include <stdexcept>

// 你的强类型枚举示例
enum class NetworkErrorCode { 
    OK = 0, 
    CONNECTION_FAILURE, 
    EMPTY_RESPONSE, 
    HOST_RESOLUTION_FAILURE, 
    UNKNOWN_ERROR = 1000 
};

struct Error {
    // 可扩展:添加更多需要支持的错误码类型到variant模板参数里
    std::variant<int, NetworkErrorCode> code;
    std::string message;

    // 模板构造函数,接受任意支持的错误码类型和消息
    template<typename CodeType>
    Error(CodeType err_code, std::string msg) 
        : code(std::move(err_code)), message(std::move(msg)) {
        // 可选:验证CodeType是否是我们支持的类型
        if (!std::holds_alternative<CodeType>(code)) {
            throw std::invalid_argument("Unsupported error code type");
        }
    }

    // 工具方法:判断当前错误码是否是指定类型
    template<typename CodeType>
    bool is() const {
        return std::holds_alternative<CodeType>(code);
    }

    // 工具方法:获取指定类型的错误码(如果类型不匹配会抛出异常)
    template<typename CodeType>
    const CodeType& get() const {
        return std::get<CodeType>(code);
    }
};

使用示例

// 创建int类型的错误
Error int_error(404, "Resource not found");
// 创建网络枚举类型的错误
Error net_error(NetworkErrorCode::CONNECTION_FAILURE, "Failed to connect to server");

// 判断错误类型并处理
if (net_error.is<NetworkErrorCode>()) {
    auto net_code = net_error.get<NetworkErrorCode>();
    if (net_code == NetworkErrorCode::CONNECTION_FAILURE) {
        // 处理连接失败逻辑
    }
}

// 如果尝试获取错误类型,会抛出std::bad_variant_access异常
// int_error.get<NetworkErrorCode>(); // 这行代码会报错

这种方案的好处是灵活易扩展,需要新增错误码类型时,只需要给variant添加新的模板参数即可,不需要修改构造函数或其他逻辑。

方案二:模板结构体+特化(适合需要定制行为的场景)

如果你需要针对不同的错误码类型实现不同的逻辑(比如不同的序列化方式、错误处理逻辑),可以用模板结构体结合特化:

#include <string>

enum class NetworkErrorCode { 
    OK = 0, 
    CONNECTION_FAILURE, 
    EMPTY_RESPONSE, 
    HOST_RESOLUTION_FAILURE, 
    UNKNOWN_ERROR = 1000 
};

// 基础模板声明
template<typename CodeType>
struct Error {
    CodeType code;
    std::string message;

    Error(CodeType c, std::string msg) : code(c), message(std::move(msg)) {}

    // 可以在这里定义通用方法,或者留空让特化版本实现
    std::string to_string() const;
};

// int类型的特化(如果需要定制逻辑)
template<>
struct Error<int> {
    int code;
    std::string message;

    Error(int c, std::string msg) : code(c), message(std::move(msg)) {}

    std::string to_string() const {
        return "Int error: " + std::to_string(code) + " - " + message;
    }
};

// 网络错误枚举的特化
template<>
struct Error<NetworkErrorCode> {
    NetworkErrorCode code;
    std::string message;

    Error(NetworkErrorCode c, std::string msg) : code(c), message(std::move(msg)) {}

    std::string to_string() const {
        // 可以把枚举转成对应的字符串
        switch(code) {
            case NetworkErrorCode::CONNECTION_FAILURE:
                return "Network error: CONNECTION_FAILURE - " + message;
            case NetworkErrorCode::EMPTY_RESPONSE:
                return "Network error: EMPTY_RESPONSE - " + message;
            default:
                return "Network error: UNKNOWN - " + message;
        }
    }
};

使用示例

Error<int> int_err(500, "Internal server error");
Error<NetworkErrorCode> net_err(NetworkErrorCode::EMPTY_RESPONSE, "Server sent empty data");

std::cout << int_err.to_string() << std::endl;
std::cout << net_err.to_string() << std::endl;

这种方案的优势是可以为每种错误类型定制专属逻辑,但缺点是新增错误类型时需要编写对应的特化结构体,相对繁琐一些。

额外小提示

  • 如果需要把错误码统一转换成int用于日志或外部接口,可以给Error结构体添加一个to_int()方法,用std::visit处理variant的不同类型,或者在模板特化中分别实现转int的逻辑。
  • 如果你还需要支持错误链(比如嵌套错误),可以在Error结构体里添加一个std::optional<Error>成员,用来存储原始错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:30:55