打包元组及其索引范围

Pack tuple with its index range

本文关键字:索引 范围 元组 包元组      更新时间:2023-10-16

我想知道是否有办法将元组与其索引范围打包(可能使用 std::index_sequence (。基本上,我想要实现的是

template <typename... Us, std::size_t... Idx>
void func(??? arg_pack) {
  // std::get<Idx>(std::move(arg_pack.args))...
}

以下内容不起作用,但说明了我的意图。

template <typename... Us, std::size_t... Idx>
struct arg_pack {
  std::tuple<Us...> args;
  std::index_sequence<Idx...> idx;
};

更新:

这是我在示例使用中实际采用的解决方案。希望这能更清楚地说明我的意图。

双可变参数列表存在常见问题:在可变参数的末尾只能有一个。

我建议将索引列表打包成一种类型(通常的std::index_sequence(并将其放在首位。

我的意思是,类似的东西

template <typename...>
struct arg_pack;
template <std::size_t ... Is, typename ... Ts>
struct arg_pack<std::index_sequence<Is...>, Ts...>
 {
   static_assert( sizeof...(Is) == sizeof...(Ts) , "!" );
   std::tuple<Ts...>          args;
   std::index_sequence<Is...> idx;
 };

所以func()可以写成如下

template <std::size_t ... Is, typename ... Ts>
void func (arg_pack<std::index_sequence<Is...>, Ts...> && ap)
 {
   using unused = int[];
   (void)unused { 0, (std::get<Is>(std::move(ap.args)), 0)... };
 }

我还建议声明(不是定义,以std::declval()的方式......但您也可以创建一个make_arg_pack(),以从declArgPack()函数的Ts...值(列表开始创建对象

template <typename ... Ts>
arg_pack<std::make_index_sequence<sizeof...(Ts)>, Ts...> declArgPack ();

简化类型的创建以及模板using类型的定义,以简化declArgPack()的使用

template <typename ... Ts>
using arg_pack_type = decltype(declArgPack<Ts...>());

以下是完整的工作示例

#include <tuple>
#include <type_traits>
template <typename...>
struct arg_pack;
template <std::size_t ... Is, typename ... Ts>
struct arg_pack<std::index_sequence<Is...>, Ts...>
 {
   static_assert( sizeof...(Is) == sizeof...(Ts) , "!" );
   std::tuple<Ts...>          args;
   std::index_sequence<Is...> idx;
 };
template <typename ... Ts>
arg_pack<std::make_index_sequence<sizeof...(Ts)>, Ts...> declArgPack ();
template <typename ... Ts>
using arg_pack_type = decltype(declArgPack<Ts...>());
template <std::size_t ... Is, typename ... Ts>
void func (arg_pack<std::index_sequence<Is...>, Ts...> && ap)
 {
   using unused = int[];
   (void)unused { 0, (std::get<Is>(std::move(ap.args)), 0)... };
 }
int main ()
 {
   arg_pack_type<short, int, long, long long>  ap0;
   func(std::move(ap0));
 }