2011-01-24 18 views
5

Estoy tratando de usar boost :: make_transform_iterator para crear un iterador para una clase personalizada cuyos datos se mantienen en un mapa y donde el iterador usa el vector de claves para acceder a los valores .Re: acceso de referencia con boost :: make_transform_iterator

En mi problema, los valores del mapa son contenedores que contienen datos de gran tamaño. Como no puedo permitirme copiar los datos, me gustaría acceder a los datos por referencia a través del iterador. Sin embargo, al hacer esto, los datos están dañados, como lo ejemplifica el resultado del ejemplo simple que he adjuntado.

Por lo que puedo decir, el problema radica en el uso del functor from_key, que se inicializa utilizando una referencia al mapa, y la semántica de boost :: make_transform_iterator.

Alguna idea de cómo podría hacer esto correctamente con boost?

Gracias,

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; 
} 

Respuesta

4

Este soy yo sólo una suposición, pero transform_iterator es una envoltura alrededor del objeto función y el iterador base. No me sorprendería si el tipo de devolución del operador de desreferencia es el mismo que el typedef para el tipo de resultado de su functor. ¿Has intentado usar un tipo de referencia como result_type-typedef?

En otras palabras cambian

typedef holder result_type; 

a

typedef holder const& result_type; 

y ver qué pasa ...

+0

que fijó él! Muchas gracias... – user588241

Cuestiones relacionadas