Using Boost 1_33_1, I get an error implying that my iterator is a const iterator (because it wont let me deref the result from find()).
$ g++ bmi_iter_tst.cpp
bmi_iter_tst.cpp: In function ‘void tst(employee_set&)’:
bmi_iter_tst.cpp:32: error: invalid initialization of reference of type ‘employee&’ from expression of type ‘const employee’
I know I am not supposed to modify any of the key values, and I don't, but I still need non-const acces sto modify other data in the container elements.
I know I have done this successfully elsewhere, I just can't see what would make this const.
The code below is derived from the original boost::multi_index
example
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
using boost::multi_index_container;
using namespace boost::multi_index;
struct employee
{
int id;
int tst;
employee(int id_):id(id_), tst(0){}
};
struct id{};
typedef multi_index_container<
employee,
indexed_by<
ordered_unique<
tag<id>, BOOST_MULTI_INDEX_MEMBER(employee,int,id)> >
> employee_set;
void tst(employee_set& s)
{
employee_set::index_iterator<id>::type it = s.get<id>().find(11);
employee& eref = *it;
eref.tst++;
}
multi_index
doesn't know that you're not going to change members which are the key values. That's why it's only implements const_iterator.
If you want to modify non-key member you can use modify
function. If you're going to change key value you can use modify_key
or replace
member functions. You can get more info here.
multi_index_container<T,...>
iterators are immutable, regardless of whether typename T
is a class type (U
) or pointer type (U*
). The maintainers chose to impose this constraint to safeguard against and emphasize the fact that modifying an element directly (i.e., through an iterator) could violate the integrity-constraints of any key-based (associative) indices of the container.
For example: An ordered_unique
index would be completely invalidated if direct modification of an element (through an iterator) caused the index to no longer be ordered or unique, and the multi_index_container
itself would have no knowledge of this change/invalidation (nor would the programmer).
Here is a verbatim explanation provided by the maintainers:
By design, index elements are immutable, i.e. iterators only grant const access to them, and only through the provided updating interface (replace, modify and modify_key) can the elements be modified. This restriction is set up so that the internal invariants of key-based indices are not broken (for instance, ascending order traversal in ordered indices), but induces important limitations in non key-based indices:
Of course, there are always ways around const-correctness, the most obvious way being const_cast
... but the spirit of C++ is that a programmer should be allowed to do anything he or she wants, even if it's potentially dangerous. C++ language/library designers simply do the best they can to discourage such uses. And hopefully, when programmers do decide to circumvent those safeguards, it's because they have good reason and know exactly what they're doing.
I hope this helps.
From the MultiIndex docs on random access indices:
As usual in Boost.MultiIndex, elements of random access indices are immutable and can only be modified through member functions replace and modify. This precludes the usage of many mutating algorithms that are nonetheless applicable to std::vectors.
This applies to ordered indexes as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With