如何将std::tuple中的各类型转换为其特定子类型?
解决方案
当然可以实现这个需求,通过C模板元编程就能将std::tuple中的每个类型展开为其内部的A和B子类型,最终合并成一个新的tuple。以下是不同C版本的实现方式:
C++17及以上版本(推荐)
利用C++17的折叠表达式和std::tuple_cat特性,写法简洁直观:
#include <tuple> struct Foo1 { struct A{}; struct B{}; }; struct Foo2 { struct A{}; struct B{}; }; // 单个Foo类型展开为包含其A、B子类型的tuple template<typename T> struct ExpandFoo { using type = std::tuple<typename T::A, typename T::B>; }; template<typename T> using ExpandFoo_t = typename ExpandFoo<T>::type; // 展开tuple中所有元素并合并 template<typename... Ts> struct ExpandTupleFrom<std::tuple<Ts...>> { using type = decltype(std::tuple_cat(ExpandFoo_t<Ts>()...)); }; template<typename Tuple> using ExpandTupleFrom_t = typename ExpandTupleFrom<Tuple>::type; // 使用示例 using myTypes = std::tuple<Foo1, Foo2>; using expandedTypes = ExpandTupleFrom_t<myTypes>; // expandedTypes 等价于 std::tuple<Foo1::A, Foo1::B, Foo2::A, Foo2::B>
原理说明
ExpandFoo模板负责将单个Foo类型转换为包含其A、B子类型的tuple;ExpandTupleFrom模板接收一个tuple类型,通过折叠表达式ExpandFoo_t<Ts>()...将每个元素展开为小tuple,再用std::tuple_cat拼接成最终的大tuple,最后通过decltype推导拼接后的类型。
C++11/14版本
如果使用较低版本的C++,可以通过模板递归实现:
#include <tuple> struct Foo1 { struct A{}; struct B{}; }; struct Foo2 { struct A{}; struct B{}; }; // 递归终止条件:返回已累积的类型组成的tuple template<typename... Accumulated> struct ExpandTupleHelper { using type = std::tuple<Accumulated...>; }; // 递归处理每个元素:将当前元素的A、B加入累积类型,再处理剩余元素 template<typename T, typename... Rest, typename... Accumulated> struct ExpandTupleHelper<std::tuple<T, Rest...>, Accumulated...> : ExpandTupleHelper<std::tuple<Rest...>, Accumulated..., typename T::A, typename T::B> {}; // 对外接口模板 template<typename Tuple> struct ExpandTupleFrom { using type = typename ExpandTupleHelper<Tuple>::type; }; template<typename Tuple> using ExpandTupleFrom_t = typename ExpandTupleFrom<Tuple>::type; // 使用示例 using myTypes = std::tuple<Foo1, Foo2>; using expandedTypes = ExpandTupleFrom_t<myTypes>; // expandedTypes 等价于 std::tuple<Foo1::A, Foo1::B, Foo2::A, Foo2::B>
原理说明
ExpandTupleHelper通过递归遍历输入tuple的每个元素,每次将当前元素的A、B子类型加入到累积的类型列表中;- 当tuple元素处理完毕时,递归终止,返回累积类型组成的最终tuple。
内容的提问来源于stack exchange,提问作者konradk
相关产品推荐
相关产品推荐

