Boost logo

Boost Users :

From: David Abrahams (dave_at_[hidden])
Date: 2004-12-20 15:13:02


David Greene wrote:
> I'm not understanding something about the interaction of map with
> the algorithms. I've got a map whose value_type is another map.
> I'd like to iterate through the map entries and add all the "sub-map"
> entries to the "primary" map. I wrote a little testcase, attached
> below. When I compile it with g++ 3.3.3, I get this:
>

<schnipp>

> What am I doing wrong?
>
> Much thanks for the help!
>
> -Dave

Here are the things I can find:

> #include <boost/mpl/fold.hpp>
> #include <boost/mpl/placeholders.hpp>
> #include <boost/mpl/copy.hpp>
> #include <boost/mpl/map.hpp>
> #include <boost/mpl/value_type.hpp>
> #include <boost/mpl/inserter.hpp>
> #include <boost/mpl/insert.hpp>
> #include <boost/mpl/pair.hpp>
>
> using namespace boost;
> using namespace boost::mpl;
>
> struct key1 {};
> struct key2 {};
>
> struct entry {
> typedef map<pair<key2, int> > types;
> };

Err, this isn't what you described. Your map has a value_type **with a
nested member called types** that is a map.

> typedef map<pair<key1, entry> > map_types;
>
> typedef fold<map_types, map_types,
> copy<value_type<map_types, _2>::types,
First of all, what is this?---------------------^^^^^
> inserter<_1, insert<_1, _2> > > >::type result;

I can only assume you meant "::type," which leads to the second problem.
Oh, I see it now; you're trying to get the "types" member out of the
result of invoking value_type. Okay, to do that you need a metafunction
that gets the types member:

   template <class Value>
   struct get_types
   {
        typedef Value::types type;
   };

now you can write:

   get_types< // The ::types member of
       value_type< // The "value" component
            map_types // (when in map_types)
         , _2 // of the current element being processed
>
>

So, IIUC, your ForwardOp is trying to use the copy algorithm with an
inserter to insert each element of the sequence returned by the above
lambda expression. One other problem is that insert<_1, _2> will have
its placeholders substituted immediately as the "fold" is evaluated. So
for each step of the copy, the same state and element will be passed.
You need to protect that placeholder expression from early substitution.
 The easiest way is to transform it into a metafunction class using the
lambda metafunction:

   copy<
       get_types< // The ::types member of
           value_type< // The "value" component
                map_types // (when in map_types)
              , _2 // of the current element being processed
>
>
     , inserter< // an inserter starting with the outer state
           _1 // (the sequence being built) as its state.
         , lambda< // [preventing early substitution]
               insert<_,_> // and inserting each element into
> // the inner state
>
>

So that would be the lambda expression you pass to fold. But I would
tend just use a two-level fold:

  typedef fold<
      map_types // sequence
    , map_types // initial state
      fold<
          get_types< // The ::types member of
              value_type< // The "value" component
                   map_types // (when in map_types)
                 , _2 // of the outer element being processed
>
>
        , _1 // starting with the outer state
        , lambda<insert<_,_> >
>
>::type result;

HTH,

-- 
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com

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