如何用C++宏定义带int转枚举转换函数的非连续值枚举?
问题:创建带int转换功能的枚举定义宏
需求
- 实现一个宏,用于定义非连续值的强类型枚举(
enum class),同时自动生成int转该枚举的辅助函数,转换失败时返回std::nullopt - 期望的枚举定义语法:
SOME_MACRO(ENUM_NAME, (foo, 1), (bar, 5), )
- 要求枚举值的定义唯一,修改时仅需改动一处,且只能基于C17标准实现,不能使用C20的
using enum语法
尝试的代码
#include <optional> #define DEFINE_ENUM_WITH_CONVERSION(EnumName, ENUM_LIST) enum class EnumName { ENUM_LIST(ENUM_ENTRY) }; std::optional<EnumName> intTo##EnumName(int value) { switch (value) { ENUM_LIST(ENUM_CASE) default: return std::nullopt; } } // Helper macros for enum definition and switch cases #define ENUM_ENTRY(name, value) name = value, #define ENUM_CASE(name, value) case value: return EnumName::name; // Define the list of enum values #define VALUE_LIST(X) X(value1, 0) X(value2, 1) // Correct usage of the macro to define the enum and the conversion function DEFINE_ENUM_WITH_CONVERSION(Value, VALUE_LIST)
遇到的问题
ENUM_CASE宏中的EnumName无法被替换为实际的枚举名称,导致编译时无法识别EnumName::name中的枚举类型。
解决方案
核心思路是让辅助宏能获取到当前的枚举名称,通过将枚举名作为参数传递给辅助宏来解决替换问题,同时优化宏的调用方式,更贴近需求中的语法:
#include <optional> // 主宏:定义枚举类和int转枚举的函数 #define DEFINE_ENUM_WITH_CONVERSION(EnumName, ...) \ enum class EnumName { \ _EXPAND_ENUM_ENTRIES(__VA_ARGS__) \ }; \ \ std::optional<EnumName> intTo##EnumName(int value) { \ switch (value) { \ _EXPAND_ENUM_CASES(EnumName, __VA_ARGS__) \ default: \ return std::nullopt; \ } \ } // 辅助宏:展开枚举条目,处理逗号问题 #define _EXPAND_ENUM_ENTRIES(...) \ __VA_OPT__(_ENUM_ENTRY(__VA_ARGS__)) #define _ENUM_ENTRY(name, value, ...) name = value, __VA_OPT__(_ENUM_ENTRY(__VA_ARGS__)) // 辅助宏:展开switch case分支,传入枚举名确保正确替换 #define _EXPAND_ENUM_CASES(EnumName, ...) \ __VA_OPT__(_ENUM_CASE(EnumName, __VA_ARGS__)) #define _ENUM_CASE(EnumName, name, value, ...) case value: return EnumName::name; __VA_OPT__(_ENUM_CASE(EnumName, __VA_ARGS__)) // 使用示例:直接按需求语法定义枚举 DEFINE_ENUM_WITH_CONVERSION(MyEnum, (foo, 1), (bar, 5), (baz, 10) ) // 测试代码 int main() { auto opt1 = intToMyEnum(1); // 得到std::optional<MyEnum>{MyEnum::foo} auto opt2 = intToMyEnum(7); // 得到std::nullopt return 0; }
方案说明
- 直接支持需求语法:无需额外定义
VALUE_LIST类的宏,直接在DEFINE_ENUM_WITH_CONVERSION中传入枚举条目列表 - 解决枚举名替换问题:
_ENUM_CASE宏接收EnumName作为参数,确保生成EnumName::name时能正确替换为实际枚举类型 - C++17兼容:使用
__VA_OPT__处理可变参数的逗号收尾问题,避免编译错误 - 强类型枚举:保持
enum class的类型安全特性,符合现代C++实践
内容的提问来源于stack exchange,提问作者Roconx
相关产品推荐
相关产品推荐

