2

Given a list of size_t values as a variadic template parameter pack, how does one make a tuple of derived types (e.g. Matrix) depending on the parameter pack in such a way, that n-th element of variadic generates Matrix<n, n+1>. For example:

make_matrix_tuple<2,3,4,5>() == make_tuple( Matrix<2,3>, Matrix<3,4>, Matrix<4,5> );

How to write make_matrix_tuple function taking in a parameter pack of size_t?

By a type derived I do not mean inheritance but dependence (?). I'm not sure what the proper term is.
Unpacking parameter pack is simple enough

template <typename ElementType, size_t... Sizes>
void make_tuple_of_vectors() { std::tuple < std::array<ElementType, Sizes> ... > tuple; }

However I believe I am a bit over my head where it comes to the next part. I was trying recursively unpack a pair of arguments from parameter pack like so:

template <typename Type, size_t size1, size_t size2>
struct dummy_matrix
{
    size_t SIZE1 = size1;
    size_t SIZE2 = size2;
    using type = Type;
};

template <size_t Iterator, typename ElementType, size_t T, size_t... Sizes>
struct unpack_two
{
    using type = typename unpack_two<Iterator - 1, ElementType, Sizes...>::type;
};

template<typename ElementType, size_t T, size_t T2, size_t... Sizes>
struct unpack_two<0, ElementType, T, T2, Sizes...>
{ 
    using type = dummy_matrix<ElementType, T, T2>;
};

So that unpack_two<N, Type, Sizes...>::type gives N-th and (N+1)-nth Matrix type.
With that, I'm stuck with something that appears sensible to me, yet the compiler disagrees harshly.

template <size_t... Sizes, size_t... Is>
auto
foo_impl(std::index_sequence<Is...>) {
    std::tuple < unpack_two<Is, float, Sizes ... >::type ... > tuple; 
    return tuple; 
}
template <size_t... Args>
void foo()
{
    auto vs = foo_impl<Args...>(std::make_index_sequence<sizeof...(Args)-1>{});
}
int main() { foo<6,9,12>(); }

I'm trying to unpack list of std::size_t Sizes for the unpack_two template, and then unpack std::index_sequence for the std::make_tuple().
I would appreciate explanations as to why my tries are failing, or even is the std::index_sequence right tool here. But I'm mostly interested in any solution to the posed problem.

max66
  • 65,235
  • 10
  • 71
  • 111
MkjG
  • 144
  • 2
  • 15

1 Answers1

5

how does one make a tuple of derived types (e.g. Matrix) depending on the parameter pack in such a way, that n-th element of variadic generates Matrix<n, n+1> [?]

Maybe using a constexpr std::array in an helper function?

An example

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

template <std::size_t, std::size_t>
struct Matrix
 { };

template <std::size_t ... Ds, std::size_t ... Is>
auto mmt_helper (std::index_sequence<Is...>)
 {
   constexpr std::array ca { Ds... };

   return std::make_tuple(Matrix<ca[Is], ca[Is+1u]>{}...);
 }

template <std::size_t ... Ds>
auto make_matrix_tuple ()
 { return mmt_helper<Ds...>(std::make_index_sequence<sizeof...(Ds)-1>{}); }

int main ()
 {
   auto mt = make_matrix_tuple<2,3,4,5>();

   using T1 = decltype(mt);
   using T2 = std::tuple<Matrix<2u, 3u>, Matrix<3u, 4u>, Matrix<4u, 5u>>;

   static_assert( std::is_same_v<T1, T2> );
 }
max66
  • 65,235
  • 10
  • 71
  • 111
  • Accepted, much cleaner than what I was trying to do. Is it possible to tweak it so that I could obtain the type of the created tuple? It appears that non-static data members cannot have a type that contains auto. – MkjG Jan 26 '20 at 21:55
  • 2
    @MkjG Jup, [here](https://godbolt.org/z/kAAbcP) is an example. – Timo Jan 26 '20 at 22:39
  • 1
    @MkjG - you should show an example of use... anyway... `decltype()` is your friend; you can follow the Timo's link for an example. – max66 Jan 27 '20 at 10:59