|
Boost Users : |
From: JOAQUIN LOPEZ MU?Z (joaquin_at_[hidden])
Date: 2006-03-14 17:09:59
Jeff Flinn wrote:
> It would be nice to have a modify_range/modify_key_range that would
apply a
> function object to each deref'd iterator in the range. Since the
multi_index
> iterator derefences to a const value_type&, one can not use
std::for_each in
> particular to apply modifications. Or am I missing something.
Hello Jeff,
I think it is possible to have what you want
without requiring that a new facility be provided
by Boost.MultiIndex itself. For you can write:
template<typename Index,typename Modifier>
void modify_range(
Index& i,typename Index::iterator first,typename Index::iterator
last,
Modifier mod)
{
while(first!=last)i.modify(first++,mod);
}
and use it as in the following example:
struct adder
{
adder(int n):n(n){}
void operator()(int& x)const{x+=n;}
private:
int n;
};
typedef multi_index_container<
int,
indexed_by<
ordered_non_unique<boost::multi_index::identity<int> >
>
> multi_index_type;
multi_index_type m;
for(int i=0;i<10;++i)m.insert(i);
modify_range(m,m.begin(),m.end(),adder(-2));
or with Boost.Lambda if you prefer:
modify_range(m,m.begin(),m.end(),_1-=2);
There is a problem, though: consider the following:
// buggy call ro modify_range
modify_range(m,m.begin(),m.end(),adder(2));
What's the problem with this? Well, after *increasing*
the value of an element, this is repositioned
further to the end of the container, and consequentely
modify_range will visit it again and engage in a
neverending loop (modulo overflows.) For this situations
you can use a special (albeit slower) variation that
records the range before starting modifying the
elements:
template<typename Index,typename Modifier>
void modify_unstable_range(
Index& i,typename Index::iterator first,typename Index::iterator
last,
Modifier mod)
{
typedef std::vector<typename Index::iterator> buffer_type;
buffer_type v;
while(first!=last)v.push_back(first++);
for(typename buffer_type::iterator it=v.begin(),it_end=v.end();
it!=it_end;i.modify(*it++,mod));
}
// calling modify_unstable_range is now OK
modify_unstable_range(m,m.begin(),m.end(),adder(2));
I hope my explanations are clear enough. Does this satisfy
your needs? You can find attached a complete example
exercising these little utilities. modify_key_range would
be a simple variation on this stuff.
HTH,
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
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