如何实现IsAnyOfTypes概念以匹配包装结构体中的类型列表
实现基于自定义类型列表的IsAnyOfTypes概念
我使用如下自定义结构体实现类型列表的参数化:
template <typename... T> struct types { };
通过它可以定义类似using MyTypes = types<int, double>的类型列表,并基于此生成其他关联类型。现在需要实现一个通用的IsAnyOfTypes概念,用于限定函数参数必须是该列表中的类型,期望能写出template <typename T> concept MyType = IsAnyOfTypes<T, ListOfTypes>这样的代码,且实现方式要像标准库的IsAnyOf那样简洁,避免递归模板和之前基于std::tuple的间接实现。
简洁实现方案
方式一:辅助模板偏特化 + 折叠表达式
通过偏特化提取types中的参数包,结合折叠表达式完成类型匹配判断:
#include <concepts> #include <type_traits> // 辅助模板,默认匹配为false template<typename T, typename Types> struct is_any_of_types_impl : std::false_type {}; // 偏特化匹配types<Ts...>,用折叠表达式判断类型是否存在 template<typename T, typename... Ts> struct is_any_of_types_impl<T, types<Ts...>> : std::bool_constant<(std::same_as<T, Ts> || ...)> {}; // 最终对外暴露的concept template<typename T, typename Types> concept IsAnyOfTypes = is_any_of_types_impl<T, Types>::value;
方式二:概念内直接模板推导(更紧凑)
无需额外辅助结构体,直接在概念中通过模板lambda推导展开类型列表:
#include <concepts> template<typename T, typename Types> concept IsAnyOfTypes = requires { // 推导types中的参数包,用折叠表达式完成匹配判断 []<typename... Ts>(types<Ts...>) { return (std::same_as<T, Ts> || ...); }(std::declval<Types>()); };
使用示例
// 定义自定义类型列表 using MyTypes = types<int, double>; // 基于IsAnyOfTypes定义专属concept template<typename T> concept MyType = IsAnyOfTypes<T, MyTypes>; // 仅接受MyTypes列表中类型的函数 void process(MyType auto value) { // 函数逻辑 } int main() { process(100); // 合法:int属于MyTypes process(3.14); // 合法:double属于MyTypes // process("test"); // 编译错误:const char*不在MyTypes中 }
这个实现完全贴合需求:没有递归模板,逻辑直接清晰,和标准库IsAnyOf的实现思路一致,仅增加了从自定义types结构体中提取参数包的步骤,避免了之前基于std::tuple的间接依赖。
内容的提问来源于stack exchange,提问作者TooTone
相关产品推荐
相关产品推荐

