Boost logo

Boost Users :

Subject: Re: [Boost-users] [MPL] Applying a boost::mpl::list to the template parameter of a type.
From: Igor R (boost.lists_at_[hidden])
Date: 2010-12-18 13:22:33


> I have a class that requires a boost::variant containing shared pointers to
> various types as follows:
>     template <typename ToySharedPtrVariant, typename ColorSharedPtrVariant>
>     class ToyPicker {
>        typedef std::pair<
>          ToySharedPtrVariant,
>          ColorSharedPtrVariant
>        > toyAndColorPair;
>        typedef std::map<
>          std::string,
>          std::vector<
>            toyAndColoPair
>          >
>        > stringToToyColorPairMap;
>        // ... methods that use the defined types...
>     }
> This class currently requires template parameters of the following form to
> compile:
>     ToyPicker<
>                boost::variant<
>                  boost::shared_ptr<ToyModel>
>                >,
>                boost::variant<
>                  boost::shared_ptr<BlueToy>,
>                  boost::shared_ptr<RedToy>,
>                  boost::shared_ptr<GreenToy>
>                >
>              > toyPicker;
> How do I use an mpl list so that I can allow the following much simpler
> definition for users, then convert it into the one above inside my class?
>     ToyPicker<
>            boost::mpl::list<
>              ToyModel
>            >,
>            boost::mpl::list<
>              BlueToy,
>              RedToy,
>              GreenToy
>            >
>          > toyPicker;

If you got you right, you map a Model to a list of Colors, right?
I'm not a TMP expert, but I'd propose something like this:

#include <boost/mpl/map.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>

using namespace boost::mpl;
using boost::shared_ptr;
using boost::variant;
using boost::make_variant_over;

// a metafunction that will map for us maps list<a, b,...> -->
list<shared_ptr<a>, shared_ptr<b>, ...>
template<class Seq, template<class> class Wrapper>
struct add_wrapper : transform<Seq, Wrapper<_> >{};

// now your picker class get template args of the form pair<model,
list<color1, color2,...> >
template<typename ModelColors>
struct picker
{
  // wrapping the model with shared_ptr and variant manually
  typedef variant<shared_ptr<typename ModelColors::first> > wrapped_model;
  // applying our metafunction to the sequence of colors, then
applying make_variant_over
  typedef typename make_variant_over<typename add_wrapper<typename
ModelColors::second, shared_ptr>::type>::type wrapped_colors;

  wrapped_colors colors_;
  wrapped_model model_;
};

struct Model1;
struct Color1;
struct Color2;
struct Color3;

int main(int argc, char* argv[])
{
  picker<pair<Model1, list<Color1, Color2> > > p;
  return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net