3

Now that my previous question has a solution, more questions arise.

I want to use the wrap_into_container meta-function with boost::mpl::transform, e.g.:

#include <vector>
#include <list>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/mpl/transform.hpp>

namespace container
{
    template <typename T> struct vector { typedef std::vector<T> type; };
    template <typename T> struct list   { typedef std::list<T> type; };
}

template<typename T, template <typename> class Container>
struct wrap_into_container
{
    typedef typename Container<T>::type type;
};

int main()
{
    namespace fusion = boost::fusion;
    namespace mpl = boost::mpl;

    typedef fusion::vector<int, float, int> vec_type;
    typedef mpl::transform< vec_type, wrap_into_container<mpl::_1, container::vector> >::type wrapped_vec_type;

    wrapped_vec_type w;
    return w.size();
}

Link to coliru

But it seems like I cannot pass a template template parameter into mpl::transform ...

How can I solve this? Please provide a C++03 solution, since I cannot use C++11.

Community
  • 1
  • 1
m.s.
  • 16,063
  • 7
  • 53
  • 88
  • `wrap_into_container` is a plain type whose `::type` is `std::vector`, right? So what template template parameter are you talking about? – iavr Apr 17 '14 at 08:37
  • The second template argument of wrap_into_container is a template template parameter. So the correct wording is "I cannot pass a Lambda Expression into mpl::transform which depends on a template template parameter" – m.s. Apr 17 '14 at 08:41

2 Answers2

3

In boost::mpl, higher order functions are written by passing a fixed type with an internal apply template member (known as a metafunction class), rather than through the use of template-template parameters. Live Example.

#include <vector>
#include <list>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/mpl/transform.hpp>
#include <iostream>

namespace container
{
    struct vector {
        template<typename T> struct apply {
            typedef std::vector<T> type;
        };
    };
    struct list   {
        template <typename T> struct apply {
            typedef std::list<T> type;
        };
    };
}

template<typename T, typename ContainerMaker>
struct wrap_into_container
{
    typedef typename ContainerMaker::template apply<T>::type type;   
};

int main()
{
    namespace fusion = boost::fusion;
    namespace mpl = boost::mpl;

    typedef fusion::vector<int, float, int> vec_type;
    typedef mpl::transform<
        vec_type,
        wrap_into_container<mpl::_1, container::vector>
    >::type wrapped_vec_type;

    wrapped_vec_type w;
    std::cout << size(w) << "\n";
    return size(w);

}
Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • Thanks! Now that you named it, I also found the corresponding boost documentation at http://www.boost.org/doc/libs/1_55_0/libs/mpl/doc/tutorial/higher-order.html – m.s. Apr 17 '14 at 09:51
1

I don't know boost::mpl, so I can only speculate from what I've seen in the documentation.

I think what you need is

template<template <typename> class Container>
struct wrap_into_container
{
    template<typename T>
    struct map
    {
        typedef typename Container<T>::type type;
    };
};

Followed by

typedef wrap_into_container<container::vector>::template map<mpl::_1> fun;
typedef transform<vec_type, fun>::type wrapped_vec_type;

In this case, fun is a class of the form C<mpl::_1> where C is a class template, and whose ::type is std::vector<mpl::_1>. I think this is what mpl::transform expects for its type map.

My only test is with my own version of transform, which works with template template arguments instead of placeholders for the type map. Check live example, where transform is defined using C++11 but the remaining part is C++03. In this example, I am only using

wrap_into_container<container::vector>::template map

as a template template argument to my transform, without the placeholder <mpl::_1>.

I hope this helps.

iavr
  • 7,547
  • 1
  • 18
  • 53
  • This works as well, but the accepted answer shows the "boost::mpl"-way of doing it. – m.s. Apr 17 '14 at 09:53
  • @m.s. Ok nice to know. For a moment I got scared and deleted my answer, but looking again at the documentation I was sure it was valid so I undeleted it :-) – iavr Apr 17 '14 at 09:56