c++template-meta-programmingboost-mpl

How to transform Parameter Pack into something else than std::tuple?


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.


Solution

  • 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;
    };