Boost logo

Boost Users :

Subject: Re: [Boost-users] reference access with boost::make_transform_iterator
From: Patrick Sauer (pat05.mlst_at_[hidden])
Date: 2011-01-24 17:55:36


Hi,

I'm trying to use boost::make_transform_iterator to create an iterator for a
custom class whose data is held in a map and where the iterator uses the
vector of keys to access the values.
In my problem, the values of the map are containers which hold large data.
Since I can't afford to copy the data, I would like to access the data by
reference via the iterator. However, when doing this,
 the data is corrupted, as is exemplified by the output of the simple
example I have attached. As far as I can tell the problem lies in the use
of the from_key functor, which is initialised using a reference to the map
and is corrupted when passed through make_transform_iterator.

Any ideas how I could do this properly using boost?

Thanks,

Patrick

#include <iostream>
#include <string>
#include <vector>

#include <boost/unordered_map.hpp>
#include <boost/iterator/transform_
iterator.hpp>
#include <boost/assign.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/ref.hpp>

using namespace boost::assign;
namespace bl = boost::lambda;

class holder
{
    public:
        holder() : v() {};
        holder( const std::vector<double>& in ) : v(in) {};

        std::vector<double>& vector() { return v; };
        const std::vector<double>& vector() const { return v; };

    private:
        std::vector<double> v;
};

class from_key
{
    public:

        typedef holder result_type;

        from_key( const boost::unordered_map<std::string, holder >& m ) :
map_(m) {};

        const holder& operator() ( const std::string& in ) const { return
map_.at(in); };

    private:
        const boost::unordered_map<std::string, holder >& map_;
};

typedef boost::transform_iterator<from_key,
std::vector<std::string>::iterator > iterator;

int main()
{
    std::vector<std::string> keys;
    keys += "1","2","3";

    std::vector<double> vals;
    vals += 1.0, 2.0, 3.0;
    holder h(vals);

    boost::unordered_map<std::string, holder > m;
    insert( m ) ( "1", h )
                ( "2", h )
                ( "3", h );

    iterator it = boost::make_transform_iterator( keys.begin(), from_key( m
) );
    iterator end = boost::make_transform_iterator( keys.begin(), from_key( m
) );

    const std::vector<double>& v = it->vector();

    std::for_each( vals.begin(), vals.end(), std::cout << bl::_1 << " " );
    std::cout << std::endl;
    std::for_each( v.begin(), v.end(), std::cout << bl::_1 << " " );
    std::cout << std::endl;
}



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