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
- Contains elements of type
- Elements are indexed using a non-unique hash
- The hash's keys are constructed using the member function
Information::number()
- The hash's keys are constructed using the member function
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