基于整数范围模板参数生成笛卡尔积的C++实现问题
解决C++中编译期模板参数到运行时映射的重复组合问题
问题场景
我正在使用一个第三方库,它提供的Numeric类必须以**precision(精度)和scale(小数位数)**作为模板参数。但我的开发场景中,这两个参数要到运行时才能确定,因此需要创建所有合法参数组合到对应模板函数的运行时映射。
要求覆盖(0, 38]范围内所有满足scale <= precision的参数组合,最终映射形式如下:
mapping = { <38, 38>: []() { /* 处理Numeric<38, 38> */ }, <38, 37>: []() { /* 处理Numeric<38, 37> */ }, ... <1, 1>: []() { /* 处理Numeric<1, 1> */ }, <1, 0>: []() { /* 处理Numeric<1, 0> */ }, }
之前的实现代码存在递归调用导致的重复组合问题,输出中出现了重复的(3,3)和(1,0),需要修复为无重复的合法组合,且方案需兼容C++17。
解决方案
核心问题是原递归逻辑存在交叉调用,导致同一参数组合被多次处理。我们可以通过分层递归的方式,先遍历所有合法的precision值,再对每个precision遍历所有合法的scale值,确保每个组合只被处理一次。
代码实现
1. 定义映射类型
#include <map> #include <functional> using funcMapType = std::map<std::pair<int, int>, std::function<void(void)>>;
2. 实现单个Precision对应的所有Scale插入逻辑
// 递归插入单个Precision下的所有Scale(从CurrentScale到0) template<int Precision, int CurrentScale> struct ScaleInserter { static void insert(funcMapType& func_map) { // 插入当前(Precision, CurrentScale)组合,替换为实际业务逻辑 func_map.emplace(std::make_pair(Precision, CurrentScale), [](){ // 示例:实例化Numeric<Precision, CurrentScale>并处理 // Numeric<Precision, CurrentScale> num; // ... 业务代码 }); // 递归处理更小的Scale ScaleInserter<Precision, CurrentScale - 1>::insert(func_map); } }; // 递归终止条件:当CurrentScale < 0时停止 template<int Precision> struct ScaleInserter<Precision, -1> { static void insert(funcMapType&) {} };
3. 实现遍历所有Precision的插入逻辑
// 递归遍历从CurrentPrecision到1的所有Precision template<int CurrentPrecision> struct PrecisionInserter { static void insert(funcMapType& func_map) { // 插入当前Precision对应的所有Scale ScaleInserter<CurrentPrecision, CurrentPrecision>::insert(func_map); // 递归处理更小的Precision PrecisionInserter<CurrentPrecision - 1>::insert(func_map); } }; // 递归终止条件:当CurrentPrecision < 1时停止 template<> struct PrecisionInserter<0> { static void insert(funcMapType&) {} };
4. 初始化映射函数
static funcMapType initializeNumericCreatorMap() { funcMapType numeric_creators; // 遍历Precision从38到1,生成所有合法组合 PrecisionInserter<38>::insert(numeric_creators); return numeric_creators; }
方案说明
这个实现通过两层递归完全避免了重复组合:
- 外层递归遍历所有precision值(从38到1)
- 内层递归对每个precision遍历所有合法的scale值(从precision到0)
每个参数组合只会被处理一次,完全符合需求,且兼容C++17标准。如果需要测试小范围参数(比如precision到3),只需将PrecisionInserter<38>改为PrecisionInserter<3>,会生成预期的无重复组合。
内容的提问来源于stack exchange,提问作者Will Ayd
相关产品推荐
相关产品推荐

