如何创建可索引访问的类型元组?早期C++版本替代pack indexing方案
如何在C++26之前实现可按索引访问的类型元组?
请问如何创建一个无需借助pack indexing即可按索引访问的类型元组?已知在C++26中可通过pack indexing实现如下简单类型元组:
template <typename... Ts> struct type_tuple { template <unsigned Index> using get = Ts...[Index]; }; using T = type_tuple<int, float, double>::get<1>; // float那么该如何在更早的C++版本中实现相同的功能?
C++11/14 实现方案
方法1:递归模板提取
通过递归展开模板参数包,逐步定位到目标索引对应的类型:
// 辅助递归模板 template <unsigned Index, typename Head, typename... Tail> struct type_at { using type = typename type_at<Index - 1, Tail...>::type; }; // 递归终止条件:索引为0时返回第一个类型 template <typename Head, typename... Tail> struct type_at<0, Head, Tail...> { using type = Head; }; template <typename... Ts> struct type_tuple { template <unsigned Index> using get = typename type_at<Index, Ts...>::type; }; // 使用示例 using T = type_tuple<int, float, double>::get<1>; // 得到float类型
方法2:复用标准库std::tuple_element
如果允许依赖标准库,直接借助std::tuple_element可以快速实现,代码更简洁:
#include <tuple> template <typename... Ts> struct type_tuple { template <unsigned Index> using get = typename std::tuple_element<Index, std::tuple<Ts...>>::type; }; // 使用示例 using T = type_tuple<int, float, double>::get<1>; // 得到float类型
C++17 实现方案
C++17的折叠表达式和编译期特性可以让我们摆脱递归,用更直观的方式实现:
#include <type_traits> #include <utility> template <unsigned Index, typename... Ts> constexpr auto pick_type(std::index_sequence<Is...>) -> std::type_identity< decltype((std::declval<Ts>(), ... , (Is == Index ? std::declval<Ts>() : std::declval<Ts>()))) >; template <typename... Ts> struct type_tuple { template <unsigned Index> using get = decltype(pick_type<Index, Ts...>(std::make_index_sequence<sizeof...(Ts)>{}))::type; }; // 使用示例 using T = type_tuple<int, float, double>::get<1>; // 得到float类型
或者另一种更简洁的写法:
#include <type_traits> #include <tuple> #include <utility> template <unsigned Index, typename... Ts> using get_type_t = std::tuple_element_t< []<unsigned... Is>(std::index_sequence<Is...>) { return (Is == Index ? Is : 0) + ...; }(std::make_index_sequence<sizeof...(Ts)>{}), std::tuple<Ts...> >; template <typename... Ts> struct type_tuple { template <unsigned Index> using get = get_type_t<Index, Ts...>; };
内容的提问来源于stack exchange,提问作者HeliumHydride
相关产品推荐
相关产品推荐

