C++存储constexpr编译期值时如何减少冗余模板参数
解决方案
1. C++17及以上版本(最优方案)
C++17引入了auto非类型模板参数占位符,可直接自动推导值的类型,完全不需要手动指定类型:
template <auto _x1, auto _x2> struct A { constexpr static decltype(_x1) x1 = _x1; constexpr static decltype(_x2) x2 = _x2; };
使用方式非常简洁,直接传入编译期常量即可:
// 自动推导x1类型为int,x2类型为double constexpr auto instance = A<10, 3.14>{}; static_assert(instance.x1 == 10); static_assert(instance.x2 == 3.14);
如果需要存储任意数量的编译期值,可以搭配可变参数模板实现通用存储类:
#include <tuple> template <auto... Args> struct ConstexprStore { template <std::size_t Index> constexpr static auto get = std::get<Index>(std::make_tuple(Args...)); }; // 使用示例 constexpr auto store = ConstexprStore<1, 2.5f, 'a', true>{}; static_assert(store.get<0> == 1); // int类型 static_assert(store.get<1> == 2.5f); // float类型
C++20中还可以搭配概念对值的类型做约束,比如要求第一个参数是整数、第二个是浮点数:
#include <concepts> template <std::integral auto _x1, std::floating_point auto _x2> struct A { constexpr static decltype(_x1) x1 = _x1; constexpr static decltype(_x2) x2 = _x2; };
2. 兼容C11/C14的方案
如果编译环境不支持C++17,可以通过宏包装decltype来避免手动写类型:
// 先定义辅助宏 #define CONSTEXPR_PARAM(val) decltype(val), val // 原有模板类不需要修改 template <class T1, T1 _x1, class T2, T2 _x2> struct A { constexpr static T1 x1 = _x1; constexpr static T2 x2 = _x2; // 注意你原代码此处笔误写为T1,会导致类型错误 }; // 使用时传入宏包装后的值即可,无需手动写类型 constexpr auto instance = A<CONSTEXPR_PARAM(10), CONSTEXPR_PARAM(3.14)>{}; static_assert(instance.x1 == 10);
补充说明:以上所有实现都完全保留了值的constexpr属性,可正常用于编译期判断、常量表达式计算等场景。
内容的提问来源于stack exchange,提问作者NicolasW
相关产品推荐
相关产品推荐

