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

如何在C++中实现编译期生成唯一错误码并映射到字符串?

C++编译期唯一错误码分配与映射实现方案

C++20及以上完全支持你需求的编译期错误码分配与字符串映射功能,以下是几种实用方案,以及类级错误处理的替代建议:

方案1:利用编译器扩展__COUNTER__(简单高效)

主流编译器(GCC/Clang/MSVC)都支持__COUNTER__宏,它会在每次调用时生成递增的唯一整数,结合constexpr数组可实现编译期的错误信息映射:

核心代码

#include <cstdint>
#include <string_view>
#include <array>
#include <utility>

// 声明类级错误:生成唯一错误码和对应信息条目
#define DECLARE_CLASS_ERROR(class_name, error_name, msg) \
    namespace class_name##_errors { \
        inline constexpr uint32_t error_name = __COUNTER__; \
        inline constexpr std::pair<uint32_t, std::string_view> error_name##_entry = {error_name, msg}; \
    } \
    using namespace class_name##_errors;

// 收集所有错误条目,需在全局cpp文件中调用
#define COLLECT_ALL_ERRORS(...) \
    inline constexpr std::array<std::pair<uint32_t, std::string_view>, sizeof...(__VA_ARGS__)> g_error_entries = {__VA_ARGS__};

// 编译期错误信息查找函数
constexpr std::string_view error_str(uint32_t code) {
    for (const auto& entry : g_error_entries) {
        if (entry.first == code) {
            return entry.second;
        }
    }
    return "Unknown error code";
}

使用示例

my_class.h:

class MyClass {
public:
    DECLARE_CLASS_ERROR(MyClass, MYERROR, "Myerror message");
    DECLARE_CLASS_ERROR(MyClass, MYOTHERERROR, "Myothererror message");

    int my_func(int input) {
        if (input < 0) {
            return -static_cast<int>(MYERROR);
        }
        return 0;
    }
};

somewhere_else.h:

class SomewhereElse {
public:
    DECLARE_CLASS_ERROR(SomewhereElse, ANOTHER_ERROR, "Another_error message");
};

全局cpp文件(如error_registry.cpp):

#include "my_class.h"
#include "somewhere_else.h"

COLLECT_ALL_ERRORS(
    MyClass_errors::MYERROR_entry,
    MyClass_errors::MYOTHERERROR_entry,
    SomewhereElse_errors::ANOTHER_ERROR_entry
);

方案2:纯标准C++20模板元编程(无编译器扩展)

如果需要完全依赖标准C++,可以用模板元编程实现编译期计数器:

核心代码

#include <cstdint>
#include <string_view>
#include <array>
#include <type_traits>

namespace error_detail {
    // 每个唯一Tag对应一个递增的错误码
    template <typename Tag>
    struct ErrorCounter {
        inline static constexpr uint32_t value = []{
            static uint32_t cnt = 0;
            return cnt++;
        }();
    };

    // 存储错误信息的模板特化
    template <typename Tag>
    struct ErrorInfo {};

    // 生成错误信息数组
    template <typename... Tags>
    constexpr auto make_error_array() {
        return std::array<std::pair<uint32_t, std::string_view>, sizeof...(Tags)>{
            {ErrorCounter<Tags>::value, ErrorInfo<Tags>::msg}...
        };
    }
}

// 注册错误:生成唯一Tag类型
#define REGISTER_ERROR(error_name, msg) \
    struct error_name##_Tag {}; \
    template <> \
    struct error_detail::ErrorInfo<error_name##_Tag> { \
        inline static constexpr std::string_view msg = msg; \
    }; \
    inline constexpr uint32_t error_name = error_detail::ErrorCounter<error_name##_Tag>::value;

// 初始化全局错误注册表
#define INIT_ERROR_REGISTRY(...) \
    inline constexpr auto g_error_entries = error_detail::make_error_array<__VA_ARGS__>();

// 编译期错误信息查找
constexpr std::string_view error_str(uint32_t code) {
    for (const auto& entry : g_error_entries) {
        if (entry.first == code) {
            return entry.second;
        }
    }
    return "Unknown error code";
}

使用示例

my_class.h:

class MyClass {
public:
    REGISTER_ERROR(MYERROR, "Myerror message");
    REGISTER_ERROR(MYOTHERERROR, "Myothererror message");

    int my_func(int input) {
        if (input < 0) {
            return -static_cast<int>(MYERROR);
        }
        return 0;
    }
};

全局cpp文件:

#include "my_class.h"
#include "somewhere_else.h"

INIT_ERROR_REGISTRY(
    MYERROR_Tag,
    MYOTHERERROR_Tag,
    ANOTHER_ERROR_Tag
);

类级错误处理的简化建议

如果项目复杂度不高,以下方案更易维护:

方案:枚举类+编译期switch

给每个类分配独立的错误码区间,用枚举类封装,通过switch实现编译期错误信息查找:

class MyClass {
public:
    enum class Error : uint32_t {
        MYERROR = 1000,    // 给MyClass分配1000-1999区间
        MYOTHERERROR = 1001
    };

    static constexpr std::string_view error_str(Error err) {
        switch(err) {
            case Error::MYERROR: return "Myerror message";
            case Error::MYOTHERERROR: return "Myothererror message";
            default: return "Unknown MyClass error";
        }
    }

    int my_func(int input) {
        if (input < 0) {
            return -static_cast<int>(Error::MYERROR);
        }
        return 0;
    }
};

方案:标准库std::error_code

适合大型项目,符合C++标准错误处理范式,支持运行期扩展:

#include <system_error>
#include <string_view>

class MyClassErrorCategory : public std::error_category {
public:
    const char* name() const noexcept override { return "MyClassError"; }
    std::string message(int ev) const override {
        switch(static_cast<uint32_t>(ev)) {
            case 1000: return "Myerror message";
            case 1001: return "Myothererror message";
            default: return "Unknown MyClass error";
        }
    }
};

inline const MyClassErrorCategory& my_class_error_category() {
    static MyClassErrorCategory cat;
    return cat;
}

enum class MyClassError : uint32_t {
    MYERROR = 1000,
    MYOTHERERROR = 1001
};

inline std::error_code make_error_code(MyClassError err) {
    return {static_cast<int>(err), my_class_error_category()};
}

namespace std {
    template<> struct is_error_code_enum<MyClassError> : true_type {};
}

// 使用方式
int MyClass::my_func(int input) {
    if (input < 0) {
        return static_cast<int>(MyClassError::MYERROR);
        // 或返回标准error_code:return make_error_code(MyClassError::MYERROR);
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 19:25:57