如何实现支持任意数量单位的C++变参Multiply模板?
实现支持任意数量单位相乘的变参模板MultiplyMany
当然可以通过递归展开变参模板来复用原有的Multiply模板,C++模板系统本身不支持运行时循环,但可以通过编译期递归的方式遍历所有单位参数,逐步将前两个单位相乘的结果与剩余单位继续运算。
实现思路
核心是利用变参模板的递归特化:
- 终止条件:当
MultiplyMany仅接收一个单位类型时,直接返回该单位对应的数值类型(与原Multiply的type<T>逻辑对齐)。 - 递归展开:当存在多个单位类型时,先将前两个单位通过原
Multiply相乘得到中间复合单位,再将该中间单位与剩余的单位参数递归传入MultiplyMany,直到所有单位处理完毕。
示例代码
假设原Multiply模板的简化定义如下(仅保留核心逻辑):
// 原有的双单位相乘模板 template <typename U1, typename U2> struct Multiply { // 模拟复合单位的元信息(比如维度、单位符号等) struct CompositeUnit { template <typename T> using type = T; // 实际项目中会是带单位属性的类型,此处简化为基础数值类型 }; // 对外暴露的数值类型别名 template <typename T> using type = typename CompositeUnit::type<T>; }; // 示例单位类型 struct Velocity { template <typename T> using type = T; }; struct Time { template <typename T> using type = T; }; struct Temperature { template <typename T> using type = T; }; struct Density { template <typename T> using type = T; };
接下来实现MultiplyMany:
// 终止特化:单个单位的情况 template <typename Unit> struct MultiplyMany { template <typename T> using type = typename Unit::type<T>; }; // 递归特化:多个单位的情况 template <typename FirstUnit, typename SecondUnit, typename... RemainingUnits> struct MultiplyMany<FirstUnit, SecondUnit, RemainingUnits...> { // 先计算前两个单位的乘积,得到中间复合单位 using IntermediateUnit = typename Multiply<FirstUnit, SecondUnit>::CompositeUnit; // 递归处理中间单位与剩余单位 template <typename T> using type = typename MultiplyMany<IntermediateUnit, RemainingUnits...>::template type<T>; };
调用方式
完全符合你的需求:
// 计算Velocity * Time * Temperature * Density的结果类型 using AccuType = MultiplyMany<Velocity, Time, Temperature, Density>::type<float>;
注意事项
- 如果你的原
Multiply模板没有单独暴露CompositeUnit(而是直接通过type<T>返回数值类型),可以调整递归逻辑:将Multiply<First, Second>::type<void>作为中间单位类型(前提是type<void>能正确表示单位元信息,而非具体数值类型)。 - 该方案兼容C11及以上标准,若使用C17及更高版本,也可以结合折叠表达式实现更简洁的写法,但递归方式的兼容性更好。
内容的提问来源于stack exchange,提问作者skrat
相关产品推荐
相关产品推荐

