A. Schorr
A. Schorr

Reputation: 121

How to expand the content of an mpl::set as template parameters of a function template

I have a function template with a variadic number of template parameters:

template <typename T1, typename... Ts>
void doSomething()
{
    ...
}

Furthermore I have an mpl set defined as follows:

template <typename... Ts>
struct MyContainerCreator
{
    using type = boost::mpl::set<Ts...>;
};

using MyContainer= MyContainerCreator<T1, T2>;

Now I want to write a function doSomethingForAll() that calls doSomething() with the types in the mpl set as template parameters. Something like:

void doSomethingForAll()
{
    //pseudocode:
    doSomething<expandTypesToTemplateParameters<MyContainer::type>>();
}

Is this possible?

Upvotes: 1

Views: 119

Answers (1)

llllllllll
llllllllll

Reputation: 16404

Essentially you want a lifting function that maps a template<class...> class TT with a mpl::set<Ts...> to TT<Ts...>.

To do this generically, write a lifter with the help of Foldable:

template<template<class...> class TT>
struct lifter {
    template<class Foldable>
    struct apply {
        template <class Left, class Current> struct one_stepper;
        template<class... Ts, class Current>
        struct one_stepper<TT<Ts...>, Current> {
          using type = TT<Ts..., Current>;
        };
        using type = typename mpl::fold<Foldable, TT<>,
                  one_stepper<mpl::_1, mpl::_2>
              >::type;
    };
};

Then you can use lift mpl container in this way:

template<class... Ts> struct foo {};
using u = lifter<foo>::apply<mpl::vector<int, long>>::type;
using v = lifter<foo>::apply<mpl::set<int, long>>::type;

Then u is foo<int, long>, v is foo<int, long> or foo<long, int> depends on mpl implementation.

With this tool, your task can be done by:

template<class... Ts>
struct doSomething_helper {
    static void do_() { doSomething<Ts...>(); }
};

void doSomethingForAll()
{
    //pseudocode:
    // doSomething<expandTypesToTemplateParameters<MyContainer::type>>();
    lifter<doSomething_helper>::apply<typename MyContainer::type>::type::do_();
}

Upvotes: 3

Related Questions