Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to instantiate template from mpl::vector

I have a mpl::vector & want to instantiate a template using the vector elements as template arguments. How is this done? Can a argument pack be used to consolidate extra mpl::vector elements?

For example:

struct A; struct B; struct C; struct D;

using args = mpl::vector<A, B, C, D>;

template<typename argA, typename argB, typename argC...>
struct derived_type;

using type_from_vector = derived_type<args>;

What is the best way to approach something like this?

Thanks.

like image 924
KentH Avatar asked Jan 29 '15 04:01

KentH


2 Answers

[Full disclosure: I am Boost.Hana's developer]

I know this question is about Boost.MPL, but let me answer using the Boost.Hana library (which is still in development). If you are using a recent Clang, you might want to give this library a try; it can do everything Boost.MPL can do, but it tries very hard to make it less painful. Here you go:

#include <boost/hana/type_list.hpp>
#include <boost/hana/type.hpp>
#include <type_traits>
namespace hana = boost::hana;

struct A; struct B; struct C; struct D;
constexpr auto args = hana::type_list<A, B, C, D>;

template<typename argA, typename argB, typename ...argC>
struct derived_type;

using type_from_vector = decltype(
    hana::unpack(args, hana::template_<derived_type>)
)::type;

static_assert(std::is_same<
    type_from_vector,
    derived_type<A, B, C, D>
>{}, "");
like image 168
Louis Dionne Avatar answered Oct 09 '22 04:10

Louis Dionne


You could either use boost::mpl::fold or std::make_index_sequence.

Both these code snippets assume using namespace boost::mpl;.

Using boost::mpl::fold:

template <typename TList, typename T> struct ExtendTList;
template<typename T, typename... Ts>
struct ExtendTList<derived_type<Ts...>, T>
{
  using type = derived_type<Ts..., T>;
};

using type_from_vector = fold<args, derived_type<>, ExtendTList<_1, _2>>::type;

Using std::make_index_sequence:

template <typename V, template<typename...> T, typename Seq>
struct MakeFromTypesAtIndices;
template <typename V, template<typename...> T, size_t ... Indices>
struct MakeFromTypesAtIndices<V, T, std::integer_sequence<size_t, Indices...>>
{
  using type = T< at<V, Indices>... >;
};

using type_from_vector = MakeFromTypesAtIndices<args, derived_type, std::make_index_sequence<size<args>::value>>::type;
like image 41
Pradhan Avatar answered Oct 09 '22 06:10

Pradhan