Boost logo

Boost Users :

Subject: [Boost-users] [MultIndex] Iterator/Range validity when modify entries.
From: Deniz Bahadir (deniz.bahadir_at_[hidden])
Date: 2016-09-08 12:22:40


Hi guys,

While trying to implementing a new feature, I came across a question
concerning iterator/range validity of boost::multi_index.

To understand the question, here is my setup:

<code>

// Database entry.
struct Entry { int key1; int key2; };
// Access-keys.
struct Index1{};
struct Index2{};

using namespace boost::multi_index;
using namespace boost;

// The multi_index database.
using Database = multi_index_container<
   Entry,
   indexed_by<
     hashed_non_unique<
       tag<Index1>,
       member<Entry, int, &Entry::key1>
>,
     hashed_non_unique<
       tag<Index2>,
       member<Entry, int, &Entry::key2>
>
>
>;

Database db;
/* ... Here db is getting filled. ... */

</code>

I obtain a range of entries from that database with the same value for
key1 through the first index and want to modify each single entry of
that range. However, I will only modify key2 (which is only used as key
in the other index)!

My main question is now:
Does modifying an entry invalidate my range although I do not modify the
member that was used as key for obtaining the range?

The code in question would possibly look like this:

<code>

auto& index1 = db.get<Index1>();
auto range = index1.equal_range(42);

for (auto it = range.first; it != range.second; ++it)
{
   index1.modify(it, [](Entry& entry)
     {
       entry.key2 = 123; // <---- Does this invalidate my range?
                          // entry.key1 is not getting modified!
     });
}

</code>

My follow-up question is then:
If the range is indeed invalidated, what would be a working solution for
that problem?

Incrementing the loop-iterator by hand before modifying the entry (and
not letting the loop do it)?
So, would the following be a valid solution?

<code>

auto& index1 = db.get<Index1>();
auto range = index1.equal_range(42);

if (range.first != range.second)
{
   auto it = range.first;
   auto end = --range.second;
   do {
     index1.modify(it++, [](Entry& entry)
       {
         entry.key2 = 123; // <---- Does this invalidate my range?
                            // entry.key1 is not getting modified!
       });
   while (it != end);
}

</code>

Of course, neither do I want to iterate over an entry twice (and thereby
modify it twice) nor do I want miss an entry.

And one last question:
Does this problem or its solution apply to all index-types or just to
hashed indexes?

Thanks for the clarification.
Deniz

PS: Oh and by the way: Boost.MultiIndex is a really cool library. :-)


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