C++17如何从Filter类型列表提取去重替换void的std::variant类型
C++17 实现方案
我们通过三个独立的模板元函数逐步完成需求,所有语法均符合C++17标准:
第一步:实现类型转换元函数
负责提取Filter的内部类型,同时将void替换为std::monostate:
#include <variant> #include <type_traits> // 单个类型转换:void替换为std::monostate template <typename T> struct FilterTypeTransform { using type = T; }; template <> struct FilterTypeTransform<void> { using type = std::monostate; }; template <typename T> using FilterTypeTransform_t = typename FilterTypeTransform<T>::type;
第二步:实现类型列表去重元函数
对转换后的类型列表做去重处理,保留类型第一次出现的顺序:
// 辅助工具:给variant的类型列表头部插入新类型 template <typename V, typename T> struct VariantPushFront; template <typename... Ts, typename T> struct VariantPushFront<std::variant<Ts...>, T> { using type = std::variant<T, Ts...>; }; template <typename V, typename T> using VariantPushFront_t = typename VariantPushFront<V, T>::type; // 辅助工具:检查类型是否存在于variant的可选类型中 template <typename V, typename U> struct TypeInVariant : std::false_type {}; template <typename U, typename... Vs> struct TypeInVariant<std::variant<Vs...>, U> : std::disjunction<std::is_same<U, Vs>...> {}; // 类型去重元函数 template <typename... Ts> struct UniqueTypes; // 空列表边界处理 template <> struct UniqueTypes<> { using type = std::variant<>; }; // 递归处理逻辑 template <typename T, typename... Rest> struct UniqueTypes<T, Rest...> { private: using UniqueRest = typename UniqueTypes<Rest...>::type; public: using type = std::conditional_t< TypeInVariant<UniqueRest, T>::value, UniqueRest, VariantPushFront_t<UniqueRest, T> >; }; template <typename... Ts> using UniqueTypes_t = typename UniqueTypes<Ts...>::type;
第三步:整合到Pipeline类
将上述元函数组合,生成最终的variant类型:
template <typename T> struct Filter { using type = T; }; template <typename... Filters> struct Pipeline { // 最终生成的去重、转换后的variant类型 using BufferType = UniqueTypes_t<FilterTypeTransform_t<typename Filters::type>...>; BufferType buffer; };
功能验证
通过静态断言验证三个需求全部满足:
#include <string> // 验证需求1:正常提取Filter内部类型 static_assert(std::is_same_v< Pipeline<Filter<int>, Filter<double>, Filter<std::string>>::BufferType, std::variant<int, double, std::string> >); // 验证需求2:自动去重重复类型 static_assert(std::is_same_v< Pipeline<Filter<int>, Filter<double>, Filter<std::string>, Filter<int>>::BufferType, std::variant<int, double, std::string> >); // 验证需求3:void替换为std::monostate且去重 static_assert(std::is_same_v< Pipeline<Filter<int>, Filter<double>, Filter<void>, Filter<int>, Filter<void>>::BufferType, std::variant<int, double, std::monostate> >);
内容的提问来源于stack exchange,提问作者Jes
相关产品推荐
相关产品推荐

