Boost logo

Boost Users :

Subject: [Boost-users] [MPL] Generating multi-index container indices based on MPL tag dispatching
From: Peter Nyssen (peter_at_[hidden])
Date: 2012-03-15 06:29:23


Hi all,

this is a follow-up of my question of yesterday (Fold a vector of pairs).
The example here is a lot more elaborate and more like the final code
I'd like to achieve.
I still get errors when compiling the code below related the use of
mpl::second<mpl::_2>.

I'm trying to generate a multi-index container type that will store
objects generated using inherit_linearly.
The objects contain a number of attributes (all int in this example)
based on a typelist of attribute tags.
I want to generate this container by providing the object type and a
index_list as shown here:
http://www.boost.org/doc/libs/1_49_0/libs/multi_index/doc/tutorial/techniques.html#mpl_synthesis

I'm trying to compose the index_list using some kind of MPL tag dispatch
based on the unique & non_unique tags to generate unique & non_unique
ordered indices for the container.
It's clear to me that the errors have to do with the MPL placeholder
expressions used in the 3 types passed to the multi_index::member
template class. This is confirmed because if I replace these 3 template
parameters by the ones which are comment out just below the program
compiles fine.

 From my previous question I get that the placeholder expressions need
to be evaluated lazily (so no ::type or ::value - obviously the code
below is thus incorrect).
I've been reading section 3.3 of the MPL book on 'Handling Placeholders'
a couple of times and from this it seems I need 3 metafunctions that
call apply<> on the passed placeholder expressions and which would
return each of the types to be passed to multi_index::member<>?

I've been trying different approaches but none have been successful...
I'm still not grasping how to handle these placeholder expressions...

I hope the great minds on this list can bring some light in my clouded
mind...

Thanks & kind regards,
Peter

//-------------------------------------------------

#include <boost/mpl/at.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/inherit.hpp>
#include <boost/mpl/inherit_linearly.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/vector.hpp>

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>

namespace mpl = boost::mpl;
namespace bmi = boost::multi_index;

enum attributeTags
{
     ATTR_1,
     ATTR_2,
     ATTR_3
};

template <int attrId>
struct AttrTraits
{
     typedef int type;
};

template <typename AttrT>
struct Attribute
{
     typedef AttrTraits<AttrT::value> ATraits;

     typename ATraits::type value;
};

template <typename AttrList>
struct Object : public boost::mpl::inherit_linearly<
         AttrList,
         boost::mpl::inherit<boost::mpl::_1,
                             Attribute<boost::mpl::_2> >
>::type {};

struct unique {};
struct non_unique {};

template <typename T>
struct is_unique : boost::false_type {};

template <>
struct is_unique<unique> : boost::true_type {};

template<typename ObjectT, typename IndicesMap>
struct ObjectContainer
{
     typedef typename mpl::fold<
         IndicesMap,
         mpl::vector<>,
         mpl::if_<
             is_unique<mpl::first<mpl::_2> >,
             mpl::push_back<
                 mpl::_1,
                 bmi::ordered_unique<
                     bmi::member<
                         Attribute<boost::mpl::second<boost::mpl::_2> >,
                         
AttrTraits<boost::mpl::second<boost::mpl::_2>::value>::type,
&Attribute<boost::mpl::second<boost::mpl::_2> >::value
// Attribute<boost::mpl::int_<0> >,
// int,
// &Attribute<boost::mpl::int_<0> >::value
>
>
>,
             mpl::push_back<
                 mpl::_1,
                 bmi::ordered_non_unique<
                     bmi::member<
                         Attribute<boost::mpl::second<boost::mpl::_2> >,
                         
AttrTraits<boost::mpl::second<boost::mpl::_2>::value>::type,
&Attribute<boost::mpl::second<boost::mpl::_2> >::value
// Attribute<boost::mpl::int_<1> >,
// int,
// &Attribute<boost::mpl::int_<1> >::value
>
>
>
>
>::type IndexList;

     typedef boost::multi_index_container<ObjectT, IndexList> Container_t;

     Container_t Container;
};

int main()
{
     typedef boost::mpl::vector<
         boost::mpl::int_<ATTR_1>,
         boost::mpl::int_<ATTR_2>,
         boost::mpl::int_<ATTR_3>
> AttributeList_1;

     typedef Object<AttributeList_1> Object_1;

     typedef mpl::vector<
         mpl::pair<unique, mpl::int_<ATTR_1> >,
         mpl::pair<non_unique, mpl::int_<ATTR_2> >
> Object_1_Indicex;

     ObjectContainer<Object_1, Object_1_Indicex> Object1Container;

     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