Nick Stokes
This is probably rather obvious, but I wasn't able to locate this guarantee in MIC docs. Take,
struct Foo { explicit Foo(Bar* b = nullptr) : bar(b) {} Bar* bar; };
int getBarValue (const Foo& f) { assert( f.bar ); return f.bar->getValue(); }
boost::multi_index< Foo, indexed_by< hashed_unique < member
>> , hashed_non_unique < global_fun > FooIndex;
void grill() { FooIndex fooIndex;
Bar* b; { auto bWork = make_unique<Bar>(); // ... fooIndex.emplace( bWork.get() ); b = bWork.get(); } fooIndex.erase(b);
// ... }
Please ignore the fact that raw-pointers are potentially dangerous etc. The question is does erase() call getBarValue() despite the fact I am using the first index?
No. No key extractor or any other user-provided functor (compare predicate, hash function etc.) is ever used when erasing an element by iterator, regardless of the index you're using to do it. If you take a look at the docs for erase(iterator) at http://www.boost.org/libs/multi_index/doc/ reference/hash_indices.html#modifiers you'll see the exception safery if guaranteedly "nothrow", which means erase can't invoke any possibily-throwing user-provided function. This applies to all indices of Boost.MultiIndex. erase(const key_type&), on the other hand, needs to determine the elements to be erased by key extraction, hashing and comparing for equality (in the case of hashed indices) or key extraction and comparing for inequality (ordered indices), which may throw as recognized by the exception safety clause in the definition, marked as "basic".
More generally, do key extractors get called *at all* except at the point of insertion?
Look for exception safety guarantees in the docs, where "nothrow" is provided you know no user-provided function is called. In particular, for hashed indices key extraction, hashing and comparison for equality is only used at * Insertion/emplacement * replace/modify * Lookup * rehash/reserve * Serialization loading (this and saving are not actually clear from docs) Joaquín M López Muñoz Telefónica