How to instantiate template from mpl::vector
Asked Answered
W

2

5

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.

Wynd answered 29/1, 2015 at 4:54 Comment(0)
N
5

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;
Nariko answered 29/1, 2015 at 5:19 Comment(1)
Thanks for the help. I guess one of the lessons here is, when in doubt, look to fold.Wynd
N
6

[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>
>{}, "");
Neon answered 30/1, 2015 at 4:18 Comment(2)
Your hana library looks very promising. MPL programming really needs to be updated for c++11/14. The very clean usage to solve my problem definitely speaks well for your library. Unfortunately, I need a production solution for today's problem, but will keep watching for your mpl/fusion/phoenix upgrade!Wynd
Thank you! I am working hard on the library and the goal is to include it in Boost during this spring. If everything works as planned, you might be able to use it in production as part of a Boost release in the near future (given a recent compiler).Neon
N
5

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;
Nariko answered 29/1, 2015 at 5:19 Comment(1)
Thanks for the help. I guess one of the lessons here is, when in doubt, look to fold.Wynd

© 2022 - 2024 — McMap. All rights reserved.