如何从分散宏调用生成BOOST_PP序列及实现类型枚举映射
用Boost预处理器从分散宏调用生成序列的解决方案
预处理器是单遍处理模型,BOOST_PP_SEQ_PUSH_BACK无法在分散的宏调用中动态构建序列——它需要在宏展开时就拿到完整的目标序列。解决这个问题的核心思路是用宏收集+统一展开的模式,通过分散调用宏逐步累积条目,最后生成完整的BOOST_PP序列。
具体实现步骤
1. 定义收集用的宏与临时序列容器
先初始化一个空的临时序列,再定义SUBSCRIPTION宏,每次调用时将包含注释的条目追加到临时序列中:
// 初始化空的临时序列 #define MY_SUBSCRIPTION_SEQ () // SUBSCRIPTION宏:接收类型、枚举值、注释,将条目追加到临时序列 #define SUBSCRIPTION(TYPE, ENUM_VAL, COMMENT) \ #define MY_SUBSCRIPTION_SEQ BOOST_PP_SEQ_PUSH_BACK(MY_SUBSCRIPTION_SEQ, (TYPE, ENUM_VAL, COMMENT))
2. 分散调用SUBSCRIPTION宏
你可以在代码任意位置调用这个宏,添加映射条目:
// 分散定义各个映射条目 SUBSCRIPTION(int, IntType, "整数类型的枚举映射") SUBSCRIPTION(std::string, StringType, "字符串类型的枚举映射") SUBSCRIPTION(double, DoubleType, "浮点数类型的枚举映射")
3. 生成枚举类与type_map特化
此时MY_SUBSCRIPTION_SEQ已经是包含所有条目完整的BOOST_PP序列,用BOOST_PP_SEQ_FOR_EACH展开生成目标代码,同时保留注释:
// 处理单个条目的宏:生成枚举值、注释,以及type_map特化 #define PROCESS_ENTRY(r, data, elem) \ BOOST_PP_TUPLE_ELEM(3, 1, elem) \ BOOST_PP_IF(BOOST_PP_EQUAL(r, BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(MY_SUBSCRIPTION_SEQ))), , ,) \ /** BOOST_PP_TUPLE_ELEM(3, 2, elem) */ \ \ template<> \ struct type_map<BOOST_PP_TUPLE_ELEM(3, 0, elem)> { \ static constexpr auto value = BOOST_PP_TUPLE_ELEM(3, 1, elem); \ static constexpr const char* comment = BOOST_PP_TUPLE_ELEM(3, 2, elem); \ }; // 生成带注释的枚举类 enum class TypeEnum { BOOST_PP_SEQ_FOR_EACH_I(PROCESS_ENTRY, _, MY_SUBSCRIPTION_SEQ) };
4. 清理临时宏(可选)
生成代码后清理临时宏,避免后续代码冲突:
#undef MY_SUBSCRIPTION_SEQ #undef SUBSCRIPTION
关键注意事项
- 处理顺序:必须先定义收集宏,再调用所有
SUBSCRIPTION,最后展开序列生成代码,否则会漏掉条目。 - 枚举逗号问题:用
BOOST_PP_SEQ_FOR_EACH_I结合BOOST_PP_IF判断是否为最后一个条目,避免生成末尾多余的逗号,兼容严格语法的编译器。 - 注释保留:将注释作为字符串存入
type_map的静态成员,或者在生成枚举时直接插入单行注释,两种方式都能保留条目的说明信息。
内容的提问来源于stack exchange,提问作者Fantastic Mr Fox
相关产品推荐
相关产品推荐

