C++模板中是否可通过索引获取可变参数列表的对应类型名?
C++可变参数模板取指定索引位置类型的实现方法
你示例里的T[0]这种直接对可变参数包用下标取类型的写法是C++语法不支持的,需要通过类型萃取实现,有两种常用方案:
方案1:使用C标准库内置的std::tuple_element(C11及以上支持,最简便)
原理是把可变参数包包装到std::tuple类型里,再用标准库提供的tuple_element萃取对应索引的类型,示例代码如下:
#include <tuple> // 假设你预先定义的三个模板类 template <typename T> struct table {}; template <typename T> struct x_axis {}; template <typename T> struct y_axis {}; namespace TableLookUp { template <class... T> struct SmartMap { private: // 取第0位类型:std::tuple_element<索引, 包含所有参数的tuple类型>::type table<typename std::tuple_element<0, std::tuple<T...>>::type> OurMap; // 取第1位类型 x_axis<typename std::tuple_element<1, std::tuple<T...>>::type> Our_x_axis; // 取第2位类型 y_axis<typename std::tuple_element<2, std::tuple<T...>>::type> Our_y_axis; }; // C++14及以上可以用更简洁的别名模板,不用写typename和::type template <class... T> struct SmartMapCpp14 { private: table<std::tuple_element_t<0, std::tuple<T...>>> OurMap; x_axis<std::tuple_element_t<1, std::tuple<T...>>> Our_x_axis; y_axis<std::tuple_element_t<2, std::tuple<T...>>> Our_y_axis; }; }
方案2:自定义类型萃取实现(适合不想引入头文件的场景)
自己写一个递归的类型萃取模板,通过偏特化匹配对应索引的类型:
// 基础模板声明 template <size_t N, typename... Ts> struct nth_type; // 偏特化:索引为0时取第一个参数类型 template <typename T, typename... Rest> struct nth_type<0, T, Rest...> { using type = T; }; // 偏特化:索引大于0时,丢弃第一个参数,索引减1递归查找 template <size_t N, typename T, typename... Rest> struct nth_type<N, T, Rest...> { using type = typename nth_type<N-1, Rest...>::type; }; // 可选:C++11及以上可以加一个别名模板简化调用 template <size_t N, typename... Ts> using nth_type_t = typename nth_type<N, Ts...>::type; // 用自定义萃取器改写你的SmartMap namespace TableLookUp { template <class... T> struct SmartMapCustom { private: table<nth_type_t<0, T...>> OurMap; x_axis<nth_type_t<1, T...>> Our_x_axis; y_axis<nth_type_t<2, T...>> Our_y_axis; }; }
注意事项
- 两种方案都要求传入的索引值小于可变参数包的长度,否则会触发编译错误
- 如果需要支持编译期索引合法性校验,可以自行在萃取模板中加
static_assert判断参数包长度
内容的提问来源于stack exchange,提问作者jojo_Aero_smith_the_dummy
相关产品推荐
相关产品推荐

