C++如何按索引获取type_list指定位置类型(优先非递归实现)
非递归实现type_list按索引取类型
不需要递归实现,也不需要绕路用std::is_same做类型匹配,直接通过参数包展开就能实现编译期定位的typeAt能力,完全不依赖std::tuple,适配传递type_list临时实例的使用场景。
实现代码
首先定义基础的type_list结构:
template<typename...> struct type_list {};
核心type_at实现,无任何递归模板实例化,编译开销极低:
#include <type_traits> template<size_t I, typename List> struct type_at; template<size_t I, typename... Ts> struct type_at<I, type_list<Ts...>> { private: // 核心技巧:通过参数包构造类型标签指针数组,按下标直接定位目标类型 static constexpr auto pick() { using void_ptr_arr = void*[]; return static_cast<std::type_identity<Ts>*>( void_ptr_arr{ static_cast<void*>(static_cast<std::type_identity<Ts>*>(nullptr))... }[I] ); } public: using type = typename decltype(pick())::type; }; // 便捷使用别名 template<size_t I, typename List> using type_at_t = typename type_at<I, List>::type;
使用示例
完全符合预期的调用形式:
using L = type_list<int, char, float, double>; // 取索引为2的类型,推导结果为float using T = type_at_t<2, L>; // 类型校验 static_assert(std::is_same_v<T, float>); // 适配传type_list临时实例的场景 template<typename... Ts> void f(type_list<Ts...>) { // 函数内部可任意获取指定位置的类型 using LastType = type_at_t<sizeof...(Ts) - 1, type_list<Ts...>>; } int main() { f(L{}); // 直接传入type_list临时实例即可 }
方案说明
- 你提到的
std::index_sequence遍历+std::is_same匹配std::integral_constant的方案可以实现功能,但属于冗余实现:不需要做类型相等判断,甚至不需要依赖std::index_sequence,上面给出的数组下标定位写法是目前编译开销最低的非递归实现,长类型列表场景下编译速度优势明显。 - 整个实现没有递归逻辑,完全依赖标准的参数包展开规则,没有引入
std::tuple相关依赖,type_list是独立的轻量结构,不会带来额外编译负担。 - 所有逻辑都在编译期完成,没有任何运行时开销,
pick函数仅用于类型推导,不会生成实际的运行时代码。
内容的提问来源于stack exchange,提问作者Chris G.
相关产品推荐
相关产品推荐

