如何反转C++初始化列表参数展开顺序以从LIFO栈构造tuple
实现方案
你可以借助编译期索引序列和C++20的模板lambda特性实现无冗余、无参数数量限制的版本,所有逻辑均在编译期展开,运行时零额外开销:
完整代码
#include <tuple> #include <utility> // 编译期生成倒序索引序列 template<std::size_t N, std::size_t... Is> constexpr auto make_reverse_index_seq(std::index_sequence<Is...>) { return std::index_sequence<(N - 1 - Is)...>{}; } template<std::size_t N> using make_reverse_index_seq_t = decltype(make_reverse_index_seq<N>(std::make_index_sequence<N>{})); template<typename... Args> [[nodiscard]] inline std::tuple<Args...> popTupleFromStack(Stack& stack) { // 步骤1:按参数包的倒序弹出元素,得到顺序相反的临时tuple auto reversed_tuple = []<std::size_t... Is>(Stack& stk, std::index_sequence<Is...>) { using RawTuple = std::tuple<Args...>; return std::tuple{stk.Pop<std::tuple_element_t<Is, RawTuple>>()...}; }(stack, make_reverse_index_seq_t<sizeof...(Args)>{}); // 步骤2:反转临时tuple得到符合要求的最终结果 return []<std::size_t... Is>(auto&& rev_tup, std::index_sequence<Is...>) { constexpr std::size_t tuple_size = sizeof...(Args); return std::tuple{std::get<tuple_size - 1 - Is>(std::forward<decltype(rev_tup)>(rev_tup))...}; }(std::move(reversed_tuple), std::make_index_sequence<sizeof...(Args)>{}); }
实现逻辑
make_reverse_index_seq_t会根据参数包长度生成倒序的索引序列,比如参数包长度为3时生成序列2,1,0- 第一步用倒序索引从原始参数包中取对应位置的类型,按这个顺序从栈中弹出元素,得到顺序反转的临时tuple:比如你要得到
tuple<int, double, string>,这一步会先弹出string、再double、再int,得到临时tupletuple<string, double, int> - 第二步再次通过索引序列把临时tuple的元素顺序反转,得到最终需要的tuple
优势
- 无需手动为不同参数数量写重载,支持任意长度的参数包
- 所有索引计算、类型推导都在编译期完成,运行时开销和手写重载版本完全一致
- 纯标准C++20实现,无第三方依赖
内容的提问来源于stack exchange,提问作者Juliean
相关产品推荐
相关产品推荐

