如何通过预处理器生成多参数模板函数的显式实例化?
多参数模板显式实例化的预处理器自动生成方案
问题背景
项目中需要为大量模板函数生成显式实例化以缩短构建时间,这些函数的模板参数组合多样,且后续可能新增函数,希望通过预处理器自动生成而非手动编写。
期望生成的代码示例:
template bool match_any<x>(); template bool match_any<y<x>>(); template bool match_expr<x,y,z>();
其中:
x取值为1到预定义max_dim的整数y可取real、bool、index三者之一z取值为0或1
需要生成所有参数组合的显式实例化,且此类函数约有100个,结构类似。
现有方案局限
目前已实现单参数的重复生成宏:
#define REP_INT_1(f) f(1) #define REP_INT_2(f) REP_INT_1(f) f(2) #define REP_INT_3(f) REP_INT_2(f) f(3) #define REP_INT_4(f) REP_INT_3(f) f(4) #define REP_INT(n,gen) REP_INT_(n,gen) #define REP_INT_(n,gen) REP_INT_##n(gen)
使用方式:
#define GEN(x) template bool match_any<x>(); REP_INT(3, GEN) #undef GEN
但该模式仅支持单参数的GEN宏,若要支持多参数,需编写大量重复宏,失去自动生成的意义。
解决方案
思路1:嵌套宏实现多参数笛卡尔积
通过嵌套不同类型的循环宏,实现多参数组合的生成,核心是让外层宏调用内层循环宏传递参数:
- 先定义类型参数的循环宏:
#define REP_TYPE_1(f) f(real) #define REP_TYPE_2(f) REP_TYPE_1(f) f(bool) #define REP_TYPE_3(f) REP_TYPE_2(f) f(index) #define REP_TYPE(n, gen) REP_TYPE_(n, gen) #define REP_TYPE_(n, gen) REP_TYPE_##n(gen)
- 生成
match_any<y<x>>的实例化(类型+整数参数):
#define GEN_MATCH_ANY_TYPE(y) \ #define GEN_INT(x) template bool match_any<y<x>>(); \ REP_INT(max_dim, GEN_INT) \ #undef GEN_INT REP_TYPE(3, GEN_MATCH_ANY_TYPE) #undef GEN_MATCH_ANY_TYPE
- 生成
match_expr<x,y,z>的实例化(三层参数组合):
#define REP_Z_1(f) f(0) #define REP_Z_2(f) REP_Z_1(f) f(1) #define REP_Z(n, gen) REP_Z_(n, gen) #define REP_Z_(n, gen) REP_Z_##n(gen) #define GEN_MATCH_EXPR_Z(z) \ #define GEN_MATCH_EXPR_TYPE(y) \ #define GEN_MATCH_EXPR_INT(x) template bool match_expr<x,y,z>(); \ REP_INT(max_dim, GEN_MATCH_EXPR_INT) \ #undef GEN_MATCH_EXPR_INT \ REP_TYPE(3, GEN_MATCH_EXPR_TYPE) \ #undef GEN_MATCH_EXPR_TYPE REP_Z(2, GEN_MATCH_EXPR_Z) #undef GEN_MATCH_EXPR_Z
思路2:可变参数宏简化多参数传递
通过__VA_ARGS__扩展循环宏,让宏支持传递多个参数给生成逻辑,减少嵌套宏的定义复杂度:
// 支持可变参数的整数循环宏 #define REP_INT_VA_1(f, ...) f(1, __VA_ARGS__) #define REP_INT_VA_2(f, ...) REP_INT_VA_1(f, __VA_ARGS__) f(2, __VA_ARGS__) #define REP_INT_VA_3(f, ...) REP_INT_VA_2(f, ...) f(3, __VA_ARGS__) #define REP_INT_VA(n, f, ...) REP_INT_VA_(n, f, __VA_ARGS__) #define REP_INT_VA_(n, f, ...) REP_INT_VA_##n(f, __VA_ARGS__) // 支持可变参数的类型循环宏 #define REP_TYPE_VA_1(f, ...) f(real, __VA_ARGS__) #define REP_TYPE_VA_2(f, ...) REP_TYPE_VA_1(f, ...) f(bool, __VA_ARGS__) #define REP_TYPE_VA_3(f, ...) REP_TYPE_VA_2(f, ...) f(index, __VA_ARGS__) #define REP_TYPE_VA(n, f, ...) REP_TYPE_VA_(n, f, ...) #define REP_TYPE_VA_(n, f, ...) REP_TYPE_VA_##n(f, __VA_ARGS__) // 三元参数生成逻辑 #define GEN_MATCH_EXPR(x, y, z) template bool match_expr<x,y,z>(); #define GEN_MATCH_EXPR_Z(z) \ #define GEN_MATCH_EXPR_TYPE(y) \ REP_INT_VA(max_dim, GEN_MATCH_EXPR, y, z) \ REP_TYPE_VA(3, GEN_MATCH_EXPR_TYPE) \ #undef GEN_MATCH_EXPR_TYPE REP_Z(2, GEN_MATCH_EXPR_Z) #undef GEN_MATCH_EXPR_Z
思路3:预处理器元编程库(可选)
如果项目允许引入外部库,使用Boost.Preprocessor这类成熟的预处理器库,可直接利用其内置的循环、序列遍历功能,无需手动编写重复的循环宏:
#include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/seq/for_each.hpp> // 定义参数序列 #define TYPES (real)(bool)(index) #define Z_VALUES (0)(1) // 生成 match_any<x> #define GEN_MATCH_ANY(z, n, data) template bool match_any<n>(); BOOST_PP_REPEAT(max_dim, GEN_MATCH_ANY, ~) // 生成 match_any<y<x>> #define GEN_MATCH_ANY_TYPE(z, type, data) \ BOOST_PP_REPEAT(max_dim, GEN_MATCH_ANY_TYPE_INT, type) #define GEN_MATCH_ANY_TYPE_INT(z, n, type) template bool match_any<type<n>>(); BOOST_PP_SEQ_FOR_EACH(GEN_MATCH_ANY_TYPE, ~, TYPES) // 生成 match_expr<x,y,z> #define GEN_MATCH_EXPR_Z(z, val, data) \ BOOST_PP_SEQ_FOR_EACH(GEN_MATCH_EXPR_TYPE, val, TYPES) #define GEN_MATCH_EXPR_TYPE(z, type, z_val) \ BOOST_PP_REPEAT(max_dim, GEN_MATCH_EXPR_INT, (type, z_val)) #define GEN_MATCH_EXPR_INT(z, n, args) template bool match_expr<n, BOOST_PP_TUPLE_ELEM(2,0,args), BOOST_PP_TUPLE_ELEM(2,1,args)>(); BOOST_PP_SEQ_FOR_EACH(GEN_MATCH_EXPR_Z, ~, Z_VALUES)
新增参数类型或数值范围时,只需修改序列定义即可,扩展性极强。
内容的提问来源于stack exchange,提问作者wittn
相关产品推荐
相关产品推荐

