Question

So I'm trying to come up with a function which converts a;

std::pair<T,std::pair<U, V>>

data type, into a std::tuple;

std::tuple<T,U,V>

It should work in the general case, with an arbitrary number of mixed type arguments, the format for the pairs is that;

  • the 'car' will always be a type,
  • the 'cdr' will always be a std::pair,
    • except for the innermost case, where the 'cdr' will be a type itself
      (however this might be a std::pair itself, as the type is arbitrary).

The number and type of arguments I want to retrieve is known in advance, through a variadic template argument.

My current progress is somewhat low, I'm been trying a few things, however it seems like the code I need is along these lines;

std::make_tuple(get<0>(pair), get<0>(get<1>(pair), get<0>(get<1>(get<1>(pair), ..., get<1>(pair)))));

However I can't seem to find a way to automatically generate this, I tried the Sequence<int...> approach, but without luck, however I do think it's something along those lines that I need to consider, for instance having a get method, which takes a variable number of indexes, and uses these to lookup multiple times, using the ordinary get method?

Was it helpful?

Solution

How about simple recursion

#include <utility>
#include <tuple>

// 1. metafunction to concatenate a type and a tuple
template<typename T, typename U> struct tuple_prepend_type;

template<typename T, typename ...U>
struct tuple_prepend_type<T, std::tuple<U...>>
{
    using type = std::tuple<T, U...>;
};

// 2. is_pair type trait
template<typename>
struct is_pair : std::false_type {};
template<typename U, typename V>
struct is_pair<std::pair<U, V>> : public std::true_type {};

// 3. the converter itself
template<typename T, typename = void>
struct pairs_to_tuple {
    using type = std::tuple<typename T::first_type,
                            typename T::second_type>;
};

template<typename T>
struct pairs_to_tuple<T, typename std::enable_if<
                         is_pair<typename T::second_type>::value
                     >::type
         >
{
    using type = typename tuple_prepend_type<
                     typename T::first_type,
                     typename pairs_to_tuple<typename T::second_type>::type
                 >::type;
};

int main()
{
    std::pair<int, std::pair<double, std::pair<bool, char> > > p;
    static_assert(std::is_same<pairs_to_tuple<decltype(p)>::type,
                               std::tuple<int, double, bool, char>>::value, "")
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top