可变参数模板类Spectrum:如何让int模板参数自动转为float?
问题:让Spectrum类模板支持整数类型的波长模板参数
我定义了如下C++类:
template <size_t N, float... Lam> requires (sizeof...(Lam) == N) class Spectrum { public: Spectrum() : wavelengths{ static_cast<float>(Lam)... } { values.fill(0.f); }; template <IsNumeric T> Spectrum(T v) : wavelengths{ static_cast<float>(Lam)... } { values.fill(static_cast<float>(v)); }; template <IsNumeric... T> requires (sizeof...(T) == N) Spectrum(T... v) : wavelengths{ static_cast<float>(Lam)... }, values { static_cast<float>(v)... } { }; ... // 其他不相关的方法/重载 private: std::array<float, N> values; const std::array<float, N> wavelengths; };
目前可以这样调用该类:
Spectrum<3, 450.f, 500.f, 600.f> color{ 1,2,3 };
它的行为符合预期:wavelengths被初始化为450.f, 500.f, 600.f,values被初始化为1.f, 2.f, 3.f。
我希望允许用户改用以下方式调用:
Spectrum<3, 450, 500, 600> color{1,2,3};
这里450是int类型,需要自动转换为float类型,类似构造函数模板中已经实现的转换逻辑,但不确定如何在类模板本身中实现这一需求。
解决方案
修改类模板的参数列表和约束,将固定的float... Lam改为auto... Lam,同时约束每个模板参数都是数值类型,就能实现自动转换:
// 先确保IsNumeric概念已定义(如果没有可以用std::is_arithmetic_v替代) template<typename T> concept IsNumeric = std::is_arithmetic_v<T>; template <size_t N, auto... Lam> requires (sizeof...(Lam) == N && (... && IsNumeric<decltype(Lam)>)) class Spectrum { public: Spectrum() : wavelengths{ static_cast<float>(Lam)... } { values.fill(0.f); }; template <IsNumeric T> Spectrum(T v) : wavelengths{ static_cast<float>(Lam)... } { values.fill(static_cast<float>(v)); }; template <IsNumeric... T> requires (sizeof...(T) == N) Spectrum(T... v) : wavelengths{ static_cast<float>(Lam)... }, values { static_cast<float>(v)... } { }; ... // 其他不相关的方法/重载 private: std::array<float, N> values; const std::array<float, N> wavelengths; };
说明
- 使用
auto... Lam作为模板参数,允许传入任何类型的编译期常量(包括int、double等算术类型) - 通过requires约束确保:
- 模板参数的数量等于N
- 每个参数都是数值类型(匹配你已有的
IsNumeric概念,或直接用std::is_arithmetic_v)
- 在初始化
wavelengths数组时,依然用static_cast<float>(Lam)...将模板参数转换为float类型,和构造函数的转换逻辑保持一致
修改后,你就可以用Spectrum<3, 450, 500, 600> color{1,2,3};这样的写法,wavelengths会被正确初始化为450.f, 500.f, 600.f。
内容的提问来源于stack exchange,提问作者Chris Gnam
相关产品推荐
相关产品推荐

