It is better explained by an example:
template <typename T1, typename T2>
struct OnePair
{
using TupleOfArgs = std::tuple<T1, T2>;
using TupleOfPairs = std::tuple<std::pair<T1, T2>>;
};
template <typename T1, typename T2, typename T3, typename T4>
struct TwoPairs
{
using TupleOfArgs = std::tuple<T1, T2, T3, T4>;
using TupleOfPairs = std::tuple<std::pair<T1, T2>, std::pair<T3, T4>>;
};
template <typename... Args>
struct NPairs
{
using TupleOfArgs = std::tuple<Args...>;
// using TupleOfPairs = ???
};
OnePair defines a tuple with one pair. TwoPairs defines a tuple with two pairs.
How do I define TupleOfPairs in NPairs so it transforms the Parameter Pack to std::tuple of pairs?
Is it possible to achieve that with the std library? Maybe with boost::mpl?
Two answers, both great. @chris uses an iterative method while @aschepler uses a recursive solution. Personally, I found the recursive solution easier to follow.
Here's one straightforward way with a recursive helper:
template <typename PairsTuple, typename... Ts>
struct ZipPairs;
template <typename PairsTuple>
struct ZipPairs<PairsTuple> { using type = PairsTuple; };
template <typename... Pairs, typename T1, typename T2, typename... Ts>
struct ZipPairs<std::tuple<Pairs...>, T1, T2, Ts...>
{
using type = typename ZipPairs<
std::tuple<Pairs..., std::pair<T1, T2>>, Ts...>::type;
};
template <class... Args>
struct NPairs
{
static_assert(sizeof...(Args) % 2 == 0);
using TupleOfArgs = std::tuple<Args...>;
using TupleOfPairs = typename ZipPairs<std::tuple<>, Args...>::type;
};