2

I have a multi index container with four indexes. One of the indexes is a random access index, used to maintain the insertion order. When a property on an element of the container is updated externally, I would like the relevant index to be updated. However, I would like to preserve the order of insertion.

I would like to know whether the order of insertion will be affected if I replace the value in question. If not, how can I achieve this?

MM.
  • 4,224
  • 5
  • 37
  • 74

1 Answers1

2

I would expect modify() to work here. Let me try it out and show an example:

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>

struct Data
{
    int i;
    std::string index1;

    friend std::ostream& operator<<(std::ostream& os, Data const& v) {
        return os << "{ " << v.i << ", '" << v.index1 << "' }";
    }

};

namespace bmi = boost::multi_index;

using Table = bmi::multi_index_container<
    Data,
    bmi::indexed_by<
        bmi::random_access<>,
        bmi::ordered_unique<bmi::member<Data, std::string, &Data::index1> >
    > >;

static std::ostream& operator<<(std::ostream& os, Table const& table) {
    os << "insertion order: "; for(auto const& element : table) os << element << "; ";
    os << "\nsecondary index: ";for(auto const& element : table.get<1>()) os << element << "; ";
    return os << "\n";
}

int main()
{
    Table table {
        { 42, "aap" },
        { 43, "noot" },
        { 44, "mies" } 
    };

    std::cout << "Before:\n" << table << "\n";

    table.modify(table.begin(),  [](Data& v) { v.i *= v.i; });
    std::cout << "Edit 1:\n" << table << "\n";

    table.modify(table.begin()+2, [](Data& v) { v.index1 = "touched"; });
    std::cout << "Edit 2:\n" << table << "\n";
}

Prints

Before:
insertion order: { 42, 'aap' }; { 43, 'noot' }; { 44, 'mies' }; 
secondary index: { 42, 'aap' }; { 44, 'mies' }; { 43, 'noot' }; 

Edit 1:
insertion order: { 1764, 'aap' }; { 43, 'noot' }; { 44, 'mies' }; 
secondary index: { 1764, 'aap' }; { 44, 'mies' }; { 43, 'noot' }; 

Edit 2:
insertion order: { 1764, 'aap' }; { 43, 'noot' }; { 44, 'touched' }; 
secondary index: { 1764, 'aap' }; { 43, 'noot' }; { 44, 'touched' }; 

Which is likely what you wanted?

See it Live On Coliru

sehe
  • 374,641
  • 47
  • 450
  • 633
  • You're quick! This answers my question. Bedankt! – MM. Apr 18 '14 at 20:44
  • @MM By the way, `replace` seems to also retain insertion order. Note, you may have to `project` an iterator from another index onto the (primary) random_access index. http://coliru.stacked-crooked.com/a/c12a04b7be451244. **Sample** with `project`-ion: http://coliru.stacked-crooked.com/a/b4f4b8ef4f70022d – sehe Apr 18 '14 at 20:52