C++可变参数模板元组类型过滤转换实现技术问询
实现元组的类型过滤转换(模板元编程方案)
嘿,刚接触模板元编程确实容易摸不着头脑,不过你的需求其实可以通过类型萃取+递归模板来实现,我给你一步步拆解怎么做:
首先,我们得先从你的filter结构体里把关键信息拿出来——也就是过滤标记(INCLUDE/EXCLUDE)和包裹的类型,这一步叫类型萃取:
enum : int { INCLUDE, EXCLUDE }; template <int filter_val, class T> struct filter { }; // 萃取filter的过滤值和内部类型的辅助模板 template <class Filter> struct filter_traits; // 针对filter特化的萃取模板 template <int Val, class T> struct filter_traits<filter<Val, T>> { static constexpr int value = Val; using type = T; }; // 定义便捷别名,避免每次写冗长的typename template <class Filter> constexpr int filter_value = filter_traits<Filter>::value; template <class Filter> using filter_type = typename filter_traits<Filter>::type;
接下来是核心的元组过滤逻辑,我们用递归模板逐个处理元组里的元素,判断是否要保留对应的类型:
#include <tuple> #include <type_traits> // 主模板:默认用空元组作为结果的初始值 template <class Tuple, class Result = std::tuple<>> struct filter_tuple; // 特化版本:处理元组的第一个元素,递归处理剩余部分 template <class First, class... Rest, class... ResultTypes> struct filter_tuple<std::tuple<First, Rest...>, std::tuple<ResultTypes...>> { // 用std::conditional判断是否保留当前元素:如果是INCLUDE,就把内部类型加入结果 using type = typename std::conditional_t< (filter_value<First> == INCLUDE), typename filter_tuple<std::tuple<Rest...>, std::tuple<ResultTypes..., filter_type<First>>>::type, typename filter_tuple<std::tuple<Rest...>, std::tuple<ResultTypes...>>::type >; }; // 递归终止条件:当原元组为空时,返回已经构建好的结果元组 template <class... ResultTypes> struct filter_tuple<std::tuple<>, std::tuple<ResultTypes...>> { using type = std::tuple<ResultTypes...>; }; // 便捷别名,直接获取过滤后的元组类型 template <class Tuple> using filter_tuple_t = typename filter_tuple<Tuple>::type;
现在来验证你的例子,看看是不是符合预期:
int main() { struct A {}; struct B {}; struct C {}; // 补全你给出的原元组 using OriginalTuple = std::tuple<filter<INCLUDE, A>, filter<EXCLUDE, B>, filter<INCLUDE, C>>; // 过滤后的目标元组 using FilteredTuple = filter_tuple_t<OriginalTuple>; // 静态断言验证类型是否正确:应该是std::tuple<A, C> static_assert(std::is_same_v<FilteredTuple, std::tuple<A, C>>, "过滤结果不符合预期"); return 0; }
如果你用的是C++17及以上版本,还可以用折叠表达式简化代码,逻辑会更直观:
// C++17+ 版本的简洁实现 template <class... Filters> auto filter_tuple_cpp17(std::tuple<Filters...>) -> std::tuple<filter_type<Filters>...> requires ((filter_value<Filters> == INCLUDE) || ...) { return {}; } // 对应的类型别名 template <class... Filters> using filter_tuple_cpp17_t = decltype(filter_tuple_cpp17(std::declval<std::tuple<Filters...>>()));
这个版本利用了C++17的折叠表达式来遍历所有filter,requires约束确保只保留INCLUDE的元素,代码量少了很多。
内容的提问来源于stack exchange,提问作者jezzi23
相关产品推荐
相关产品推荐

