Dina Benyamin
Dina Benyamin

Reputation: 97

C++ templates - How can I unpack a tuple of tuples of template arguments?

So I have this implementation of a tuple:

template<typename... TT>
struct Tuple { 
    enum{ size = sizeof...(TT) };
};

Now I'm trying to define a struct which gets a tuple of tuples to represent a 2D array in compile time. For example, usage:

template <int T>
struct Int {
    enum { value = T };
};

typedef Matrix< Tuple<
        Tuple < Int<1>, Int<2>, Int<3> >,
        Tuple < Int<4>, Int<5>, Int<6> >
> > arr;
int width = arr::width; // width should be 3 as number of columns.
int length = arr::length; // length should be 2 as number of rows.

I have tried this approach:

template <typename TupleOfTuples>
struct Matrix;

template<typename ... TT>
struct Matrix<Tuple<Tuple<TT...>>> {
    enum { width = Tuple<TT...>::size };
    enum { length = Tuple<Tuple<TT...>>::size };
};

This seems to work ONLY when length = 1 (matrix of only one row).
For every other length I get the error message:

error: incomplete type 'arr {aka Matrix<Tuple<Tuple<Int<1>, Int<2>, Int<3> >, Tuple<Int<4>, Int<5>, Int<6> > > >}' used in nested name specifier
     int width = arr::width;


I have also tried to mess around with the struct's declaration but nothing seemed to work!
How can I make this work?

Upvotes: 2

Views: 497

Answers (1)

Jaa-c
Jaa-c

Reputation: 5157

What you did here can't work:

template<typename ... TT>
struct Matrix<Tuple<Tuple<TT...>>> 

Because you create a specialization for Matrix with a Tuple that contains exactly one Tuple. Therefore template deduction fails for this case.

You need to extract the first tuple from the nested tuple and take it's size. This assumes that all nested tuples have the same size:

template <class T1, class... T>
struct first
{
    using type = T1;
};

template <int T>
struct Int
{
    static constexpr auto value = T;
};

template<typename... TT>
struct Tuple 
{ 
    static constexpr auto size = sizeof...(TT);
};

template<typename... TT>
struct Matrix; 

template<typename... TT>
struct Matrix<Tuple<TT...>> 
{
    static constexpr auto width = Tuple<TT...>::size;
    static constexpr auto length = first<TT...>::type::size;
};

int main()
{
    using arr = Matrix< Tuple<
        Tuple < Int<1>, Int<2>, Int<3> >,
        Tuple < Int<4>, Int<5>, Int<6> >>>;

    std::cout << arr::width << arr::length << std::endl;
}

This outputs 23

Upvotes: 3

Related Questions