C++17:如何实现非模板类型与任意实例化模板类型的constexpr类型检查
解决任意模板实例与非模板类型的constexpr类型检查问题
核心思路
通过模板特化实现类型是否为指定模板任意实例的判断,再结合可变参数模板封装通用检查逻辑,同时兼容非模板类型的判断,避免重复代码。
实现代码
1. 模板实例判断Trait
首先定义一个通用Trait,用来检测某个类型是否是目标模板的任意实例:
// 基础模板:默认判定为false template <template <auto> class Template, typename T> struct is_instantiation_of : std::false_type {}; // 特化版本:匹配Template<N>的实例 template <template <auto> class Template, auto N> struct is_instantiation_of<Template, Template<N>> : std::true_type {}; // 辅助constexpr变量,简化调用 template <template <auto> class Template, typename T> constexpr bool is_instantiation_of_v = is_instantiation_of<Template, T>::value;
2. 通用类型检查函数
封装一个可变参数的constexpr函数,同时支持非模板类型和模板实例的判断:
#include <type_traits> // 基础重载:匹配非模板类型的直接判断 template <typename Target, typename T> constexpr bool is_one_of(T&&) { return std::is_same_v<std::decay_t<T>, Target>; } // 模板实例专用重载:匹配目标模板的任意实例 template <template <auto> class TargetTemplate, typename T> constexpr bool is_one_of(T&&) { return is_instantiation_of_v<TargetTemplate, std::decay_t<T>>; } // 可变参数版本:递归检查所有目标类型/模板 template <typename First, typename... Rest, typename T> constexpr bool is_one_of(T&& val) { return is_one_of<First>(val) || is_one_of<Rest...>(val); }
3. 使用示例
假设我们有以下类型定义:
// 非模板类型 struct type2 {}; // 带非类型模板参数的模板 template <auto N> struct type1 {}; // 测试用例 constexpr bool test1 = is_one_of<type1, type2>(type1<5>{}); // true constexpr bool test2 = is_one_of<type1, type2>(type2{}); // true constexpr bool test3 = is_one_of<type1, type2>(int{}); // false constexpr bool test4 = is_one_of<type1>(type1<100>{}); // true
扩展说明
- 对于其他带非类型参数的模板,直接复用
is_instantiation_of即可,无需重复编写判断逻辑 - 如果需要支持不同类型的非模板参数(比如同时支持
size_t和int),只需调整is_instantiation_of的特化逻辑,或者针对不同模板参数类型做特化 - 可变参数版本支持同时传入任意数量的非模板类型和模板,一次性完成多类型检查
内容的提问来源于stack exchange,提问作者Takatoshi Kondo
相关产品推荐
相关产品推荐

