jeudi 12 mars 2015

Modifying key ranges in a Boost Multi-Index Map having hashed_non_unique keys


Vote count:

0




I'm trying to update a range of elements in a multi-index map, but it's seems a little more complicated than I expected it to be..


Given the following declarations:



struct Information {

int number() const {
return number_;
}

int number_;
};


typedef boost::multi_index_container<
Information,
boost::multi_index::indexed_by<
boost::multi_index::hashed_non_unique<
boost::multi_index::tag<int>,
boost::multi_index::const_mem_fun<
Information,
int,
&Information::number
>
>
>
> Information_Map;

Information_Map information_map_;


The following is a summary of what's declared above:



  • A struct Information, which contains an arbitrary number, which is not unique

  • A multi-index map with the following properties



    • Contains elements of type Information





    • Elements are indexed using a non-unique hash





    • The hash's keys are constructed using the member function Information::number()




Now, I also have declared something like this:



struct Plus_One_Modifier {
void operator()(Information& obj) const {
obj.number_ += 1;
}
};


The previous struct is a modifier, which is expected to be used when calling the modify function:



// from boost/multi_index/hashed_index.hpp
template<typename Modifier> bool modify(iterator position,Modifier mod);


Everything works as expected when this function is used to modify only one element:



// Updates the first element
Information_Map::index<int> index = information_map_.get<int>();
index.modify(index.begin(), Plus_One_Modifier());


The problem is that, in one special case, I have to update the whole container, something like this:



// Update the whole container the first element
Information_Map::index<int> index = information_map_.get<int>();
for (Information_Map::index<int>::iterator it = index.begin();
it != index.end();
++it) {
index.modify(it, Plus_One_Modifier());
}


The previous codes fails to transverse the whole container in most cases, at some point the iterator is modified in a way that ++it is equal to end.


I found that using a third variable seems to alleviate the problem, but I'm not convinced it's correct because it is making more iterations than elements in the container..



// Update the whole container the first element
Information_Map::index<int> index = information_map_.get<int>();
Information_Map::index<int>::iterator begin = index.begin();
Information_Map::index<int>::iterator end = index.end();
while (begin != end) {
Information_Map::index<int>::iterator it = begin++;
index.modify(it, Plus_One_Modifier());
}


So, the problem is:



  • I want to modify all elements in the container

  • Modifying an element affects the way the element is indexed in the container, i.e: modifies the key

  • Modifying the key affects the way elements are stored in the container, which means iterators can get a little messy


And I'm looking for a safe way of updating a range of elements in the container.


The only solution that has come to my mind is the following:



  • List all elements in the container

  • Navigate through the list and modify elements one by one


This will work OK, but the performance impact is too big


Any help will be appreciated



asked 48 secs ago

ichramm

2,085






Modifying key ranges in a Boost Multi-Index Map having hashed_non_unique keys

Aucun commentaire:

Enregistrer un commentaire