如何判断类型是否为含类型/非类型模板参数的模板特化?
解决方案
可以通过C++20的可变非类型模板参数和模板模板参数的约束,实现一个通用的解决方案,同时合并类型与非类型版本为单个concept。
通用实现代码
#include <type_traits> // 基础模板:默认匹配失败 template <template <auto...> typename C, typename T> struct instance_impl : std::false_type {}; // 特化:匹配任意非类型参数的模板特化 template <template <auto...> typename C, auto... Args> struct instance_impl<C, C<Args...>> : std::true_type {}; // 特化:匹配任意类型参数的模板特化(auto兼容类型参数) template <template <typename...> typename C, typename... Args> struct instance_impl<C, C<Args...>> : std::true_type {}; // 统一的concept template <template <auto...> typename C, typename T> concept instance_of = instance_impl<C, std::decay_t<T>>::value; // 可选:针对仅类型参数模板的明确约束 template <template <typename...> typename C, typename T> concept instance_of_type = instance_impl<C, std::decay_t<T>>::value;
验证示例
#include <iostream> #include <complex> // 仅含非类型参数的模板 template <bool...> class bools; template <int, double> class num_vals; // 仅含类型参数的模板 template <typename...> class type_pack; int main(){ // 测试类型参数模板 std::cout << instance_of<std::complex, std::complex<double>> << '\n'; // 输出1 std::cout << instance_of<type_pack, type_pack<int, float, char>> << '\n'; // 输出1 // 测试非类型参数模板 std::cout << instance_of<bools, bools<true, false, true>> << '\n'; // 输出1 std::cout << instance_of<num_vals, num_vals<42, 3.14>> << '\n'; // 输出1 // 测试不匹配的情况 std::cout << instance_of<std::complex, int> << '\n'; // 输出0 std::cout << instance_of<bools, num_vals<1, 2.0>> << '\n'; // 输出0 return 0; }
方案说明
- 通用参数兼容:C++20允许
auto...作为模板模板参数的参数列表,同时兼容类型参数(类型可隐式适配auto)和任意类型的非类型参数,无需为每种非类型参数单独编写特化。 - 双重特化覆盖:两个特化版本分别匹配类型参数模板、非类型参数模板的特化实例,确保两种场景都能正确识别。
- 单个concept统一判断:
instance_of直接复用instance_impl的结果,实现类型与非类型模板特化的统一检查。 - 兼容性补充:如果需要明确约束仅类型参数的模板,可以保留
instance_of_type,其逻辑与通用版本一致,仅模板模板参数的声明更精准。
内容的提问来源于stack exchange,提问作者Nathan29006781
相关产品推荐
相关产品推荐

