How to take nested parameter packages in variable templates?

How can I express that each parameter in the parameter package for the variation template is itself a parameter package?

Consider this code:

template <typename... TS>
void use_tuple(std::tuple<TS...> arg0);

template <typename... TS0, typename... TS1>
void use_tuple(std::tuple<TS0...> arg0, std::tuple<TS1...> arg1);

I want to use_tuplebe able to accept any number of tuples. Right now I have to write this as follows:

template <typename... TS0, typename... REST>
void use_tuple(std::tuple<TS0...> arg0, REST... rest);

void use_tuple();  // Terminates the recursion.

But I want to write it like this:

// Each ELEMENT in PACK_OF_PACKS is a parameter pack.
template <(typename...)... PACK_OF_PACKS>
void use_tuple(std::tuple<PACK_OF_PACKS...>... args);

Is it possible? If so, how? If not, what else can I do? My goal for this code is to get the types contained in all tuples.

My ultimate goal is as follows:

template <typename...> void foo();

use_tuple(std::tuple<int, float, char>{},
          std::tuple<double, short, std::string>{},
          std::tuple<std::function<void()>, std::vector<int>>{});
// Results in a call to
// foo<int, float, char, double, short, std::string,
//     std::function<void()>, std::vector<int>>();

But I want to implement this in a small, constant number of directions that are independent of the number of tuples passed in or the number of elements in each. Therefore there is no recursion.

+4
3

, ?

Tuples..., use_tuple?

template <typename...>
using example = int;

template <typename... Ts>
void foo(Ts...) { }

template <typename... Tuples>
void use_tuple(Tuples...)
{
    foo(typename types<Tuples>::template apply<example>{}...);
}

types :

template <typename Tuple>
struct types;

template <typename... Ts>
struct types<std::tuple<Ts...>>
{
    template <template <typename...> class T>
    using apply = T<Ts...>;
};

wandbox

+1

- , .

, , . PACK_OF_PACKS . std::tuple_cat.
- :

template<typename... T>
void do_use_tuple(std::tuple<T...>) {
    // T are the types you are looking for
}

template <typename... T>
void use_tuple(T&&... tuple) {
    return do_use_tuple(std::tuple_cat(std::forward<T>(tuple)...));
}

, decltype, .

. .


, , , - :

template<typename T>
struct tag { using type = T; };

template<typename... T, typename F>
void use_one(std::tuple<T...> &&, F f) {
    F(tag<T>{}...);
}

template <typename... T>
void use_tuple(T&&... tuple) {
    int arr = { 0,
        (use_one(std::forward<T>(tuple), [](auto... tag) {
            // tag::type contains the types of each
            // parameter of a tuple, a tuple at a time
       }), 0)...
    };
    (void)arr;
}

, .

+1

I assume that you have something like the following (C ++ 17). Let me emphasize that I do not recommend it. You need to clearly choose std::tuple_cat.

http://coliru.stacked-crooked.com/a/c64f2cb9a79af3e2

#include <array>
#include <iostream>
#include <tuple>
#include <utility>

////////////////////////////////////////////////////////////////////////////////

template<class... Ts>
void foo() {
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}

////////////////////////////////////////////////////////////////////////////////

namespace detail {

struct Index {
  std::size_t outer{};// identify the tuple
  std::size_t inner{};// identify the element in the tuple
};

template<std::size_t... ns, class... Tuples>
constexpr void use_tuple(std::index_sequence<ns...>, Tuples...) {
  constexpr auto inds = [&] () {
    std::array<Index, sizeof...(ns)> inds{};
    std::size_t n = 0;

    for(std::size_t outer=0; outer<sizeof...(Tuples); ++outer) {
      std::size_t size = std::begin({std::tuple_size<Tuples>::value...})[outer];
      for(std::size_t inner=0; inner<size; ++inner) inds[n++] = {outer, inner};
    }

    return inds;
  }();

  using TupleTuple = std::tuple<Tuples...>;

  foo<
    std::tuple_element_t<
      inds[ns].inner,
      std::tuple_element_t<inds[ns].outer, TupleTuple>
    >...
  >();
}

}// detail

template<class... Tuples>
constexpr void use_tuple(Tuples... tuples) {
  constexpr std::size_t N = (std::tuple_size<Tuples>{} + ...);
  detail::use_tuple(std::make_index_sequence<N>{}, std::move(tuples)...);
}

////////////////////////////////////////////////////////////////////////////////

int main() {
  std::tuple<int, unsigned, int> t0;
  std::tuple<double, float> t1;
  std::tuple<char, bool, bool, int> t2;

  use_tuple(t0, t1, t2);

  return 0;
}
0
source

Source: https://habr.com/ru/post/1689794/


All Articles