C++17中推导非类型模板参数类型并强制所有模板参数同类型的实现方法
C++17中推导非类型模板参数类型并强制所有模板参数同类型的实现方法
嘿,我来帮你搞定这个C++17的模板难题!你想要的是让模板自动从第一个非类型参数推导类型,同时严格要求所有后续参数必须和它的类型完全一致——哪怕隐式转换能过也不行,对吧?下面一步步给你讲具体实现:
1. 两个模板参数的基础实现
先给你吃颗定心丸:C17完全支持auto作为非类型模板参数,这个特性就是C17引入的,完全符合你的编译目标。
你之前尝试的template <auto min_v, decltype(min_v) max_v>之所以能让num_range<-10, 12U>编译通过,是因为编译器允许把unsigned int的12U隐式转成int(毕竟值在int范围内)。但如果要彻底杜绝这种不同类型的参数,就得用static_assert做严格的类型检查,不给隐式转换留空子:
#include <type_traits> template <auto min_v, auto max_v> struct num_range final { using num_type = decltype(min_v); // 强制检查两个参数的类型完全相同,不允许隐式转换 static_assert(std::is_same_v<decltype(min_v), decltype(max_v)>, "错误:min和max必须是完全相同的类型!"); constexpr static num_type min = min_v; constexpr static num_type max = max_v; };
这样一来,num_range<-10, 12U>会直接触发编译错误,完美符合你要的强制类型一致的需求。
2. 可变参数模板的实现(支持任意数量参数)
如果要支持任意数量的非类型模板参数,并且全部强制和第一个参数的类型一致,我们可以用C++17的折叠表达式来实现批量类型检查:
#include <type_traits> #include <array> #include <algorithm> template <auto first_val, auto... rest_vals> struct num_range final { using num_type = decltype(first_val); // 用折叠表达式遍历所有后续参数,检查类型是否和第一个完全一致 static_assert((std::is_same_v<decltype(first_val), decltype(rest_vals)> && ...), "错误:所有模板参数必须是完全相同的类型!"); // 存储第一个参数(也可以根据需求计算全局min/max) constexpr static num_type first = first_val; // 可选:把所有参数存储到constexpr数组中 constexpr static std::array<num_type, 1 + sizeof...(rest_vals)> all_values = {first_val, rest_vals...}; // 可选:计算所有参数中的最小值 constexpr static num_type global_min = [](auto... vals) { num_type current_min = first_val; ((current_min = std::min(current_min, static_cast<num_type>(vals))), ...); return current_min; }(rest_vals...); // 可选:计算所有参数中的最大值 constexpr static num_type global_max = [](auto... vals) { num_type current_max = first_val; ((current_max = std::max(current_max, static_cast<num_type>(vals))), ...); return current_max; }(rest_vals...); };
这个实现里,不管你传多少个模板参数,只要有一个类型和第一个不一样,就会触发编译错误。比如num_range<5, 10, 15U>会直接报错,而num_range<3.14, 2.71, 1.618>就能正常工作(所有参数都是double类型)。
备注:内容来源于stack exchange,提问作者Tomáš Zato
相关产品推荐
相关产品推荐

