Boost logo

Boost Users :

Subject: Re: [Boost-users] [MultiIndex] Iterator validity when modifying equal_range keys
From: Ovanes Markarian (om_boost_at_[hidden])
Date: 2011-09-03 03:06:09


Hello

thanks for your answers, please see my comments below....

On Fri, Sep 2, 2011 at 9:25 PM, Joaquin M Lopez Munoz <joaquin_at_[hidden]>wrote:

> Ovanes Markarian <om_boost <at> keywallet.com> writes:
>
> >
> > Hello *,
> >
> > reading this page
>
> What page?

Sorry forgot to include the link. I assumed this page applies here:
http://www.boost.org/doc/libs/1_46_1/libs/multi_index/doc/tutorial/indices.html#guarantees

> > states only that iterator validity is preserved for hashed indices.
> > I have a multi-index container with ordered_non_unique entries.
>
> Iterator validity is preserved for all types of indices.
>
> > Is it safe to find a matching range and modify the keys there?
>
> In general no, see above.
>
> >
> > Here an example:
> >
> >
> > entry_data& entries = indexed; //get the view to the MI-Container
>
> What is this supposed to do? Usually you get an index view
> using get(), which you're not using here.
>
I thought I am getting an index view here. Isn't it done implicitly... Why
am I suppose to use it than?
The upper statement can be seen as:

my_index_container_type::index<named_tag>::type& entries = indexed;

If I am not suppose to do that this way, why does this code compile? I know
the docs state I should use the
my_index_container_type::get<...> member, by how is this construct should be
different?

>
> >
> > for(iterator_range<entry_data::iterator> r
> >
> > = entries.equal_range(boost::make_tuple(false))
> > ; !r.empty()
> > ; r.advance_begin(1)
> > )
> > {
> > index_data d = r.front();
> >
> > d.masked = true;
> > entries.replace(r.begin(), d);
> > }
> >
> >
> > Here updated d.masked field is a first member of the composite key.
> > What happens if I do the update as shown upon?
>
> This fails for two reasons:
>
> 1. After entries.replace(...), r.begin() points to a modified
> element that is out of its original range; hence, r is no
> longer a proper range (in this particular example, its begin
> iterator will point beyond its end iterator.)
>
Ok, thanks...

>
> 2. As elements are reordered, some of them can potentially
> be relocated *before* r.end(), so even if you fix problem
> #1 you still can end up visiting elements twice.

Ok, this was also my doubt ;)

> > Would it be more efficient to iterate backwards and do the
> > update, since than all the elements will not be rearranged?
>
> Not really, since other types of similar problems crop
> up. The following is a possible solution (using iterator pairs
> rather than ranges since ranges here seem to be more noisy that
> useful):
>
> std::pair<entry_data::iterator,entry_data::iterator> p=
> entries.equal_range(boost::make_tuple(false));
> if(p.first!=p.second){ // non-empty range
> --(p.second); // solve problem #2
> for(;;){
> bool end=(p.first==p.second);
> index_data d=p.first;
> d.masked=true;
> entries.replace((p.first)++,d); //++ solves problem #1
> if(end)break;
> }
> }
>
> > Is there also any way to use modify_key with composite index or
> > are composite index key extractors always read-only?
>
>
> composite_key extractors return an opaque type called
> composite_key_result that you might esentially trat as
> read-only:
>
>
> http://www.boost.org/libs/multi_index/doc/reference/key_extraction.html#composite_key_result
>
> So the short answer is you can't use modify_key with
> composite keys.
>
Ok thanks for your help and a great lib!

With Kind Regards,
Ovanes



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