如何在C++中获取tuple的前N个元素?
获取std::tuple前N个元素的最优实现
问题描述
我有如下C++函数,需要获取tuple的前N个元素,该如何实现?
template<std::size_t N, class... Ts> void foo(Ts... ts){ std::tuple<Ts...> all_elements(ts...); auto first_elements = // 获取tuple all_elements的前N个元素 }
请问该如何定义first_elements来获取all_elements元组的前N个元素?
一、C++20及以上版本(最简洁实现)
C++20的lambda模板参数特性可以让我们无需额外辅助函数,直接在函数内生成编译期索引序列来构造目标tuple:
template<std::size_t N, class... Ts> void foo(Ts... ts){ std::tuple<Ts...> all_elements(ts...); // 生成0到N-1的编译期索引,逐个取出元素构造新tuple auto first_elements = [&]<std::size_t... Is>(std::index_sequence<Is...>) { return std::make_tuple(std::get<Is>(all_elements)...); }(std::make_index_sequence<N>{}); }
二、兼容C++17及更低版本的方案
如果需要适配C++17等低版本,可以借助std::integer_sequence和辅助函数实现,以下是完整可运行代码:
#include <tuple> #include <utility> #include <iostream> #include <type_traits> template<typename T, T... ints, class... DTs> auto reduce_tuple(std::integer_sequence<T, ints...>, std::tuple<DTs&&...>&& t){ return std::forward_as_tuple((std::move(std::get<ints>(t)))...); } template<std::size_t N, class... Ts> auto foo(Ts... ts){ std::tuple<Ts&&...> all_elements(std::forward<Ts>(ts)...); return reduce_tuple(std::make_index_sequence<N>{}, std::move(all_elements)); } // 使用示例 int main(){ auto t = foo<2>(3, "a", 0.1); static_assert(std::is_same_v<decltype(t), std::tuple<int, const char*>>); std::cout << std::get<0>(t) << " " << std::get<1>(t) << "\n"; }
代码说明
reduce_tuple通过编译期索引序列,逐个取出原tuple的对应位置元素,用std::forward_as_tuple构造保持引用类型的新tuple;foo函数通过完美转发参数构造右值引用tuple,避免不必要的拷贝;- 示例中通过
static_assert验证了生成的tuple类型符合预期,运行后会输出3 a。
内容的提问来源于stack exchange,提问作者Sam Moldenha
相关产品推荐
相关产品推荐

