[multi_index] sorted iteration of values
Hello, I'm trying to use Boost.MultiIndex to store my data. The idea is to have a kind of bidirectional multimap (I initially started with Boost.BiMap) which could model : std::multimap< SomeType*, std::set< int > > left; std::multimap< int, SomeType*> right; I'll need to : . insert obviously . remove all ints based on a SomeType* . remove one given (SomeType*,int) . for a given int iterate on all SomeType* . for a given SomeType* iterate in order on all ints What I have so far is : typedef SomeType* First; typedef int Second; struct Value { First first; Second second; }; boost::multi_index::multi_index_container< Value, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::composite_key< Value, boost::multi_index::member< Value, First, &Value::first >, boost::multi_index::member< Value, Second, &Value::second > > >, boost::multi_index::ordered_non_unique< boost::multi_index::member< Value, Second, &Value::second > >, boost::multi_index::ordered_non_unique< boost::multi_index::member< Value, First, &Value::first > > > > data; This works, except for the ints iteration based on a given SomeType* because I need them to be sorted, and they're not, e.g. auto range = data.get< 2 >().equal_range( someTypePtr ); for( auto it = range.first; it != range.second; ++it ) ; does not iterate in a sorted order. Is there a way to achieve this without manually sorting the iterated values ? Thank you ! MAT.
On 04/09/2013 07:15, Mathieu Champlon wrote:
Hello,
I'm trying to use Boost.MultiIndex to store my data. The idea is to have a kind of bidirectional multimap (I initially started with Boost.BiMap) which could model :
std::multimap< SomeType*, std::set< int > > left; std::multimap< int, SomeType*> right;
Sorry, that should be : std::map< SomeType*, std::set< int > > left; std::multimap< int, SomeType*> right; MAT.
El 04/09/2013 7:15, Mathieu Champlon escribió:
Hello,
[...]
typedef SomeType* First; typedef int Second;
struct Value { First first; Second second; };
boost::multi_index::multi_index_container< Value, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::composite_key< Value, boost::multi_index::member< Value, First, &Value::first >, boost::multi_index::member< Value, Second, &Value::second > > >, boost::multi_index::ordered_non_unique< boost::multi_index::member< Value, Second, &Value::second > >, boost::multi_index::ordered_non_unique< boost::multi_index::member< Value, First, &Value::first > > > > data;
This works, except for the ints iteration based on a given SomeType* because I need them to be sorted, and they're not, e.g.
auto range = data.get< 2 >().equal_range( someTypePtr ); for( auto it = range.first; it != range.second; ++it ) ;
does not iterate in a sorted order.
Use index #0: auto range = data.get< 0 >().equal_range( someTypePtr ); In fact, you can get rid of index #2: when using a composite key you can search by providing only the first m fields of the key, so for all practical purposes index #2 is redundant with #0. Joaquín M López Muñoz Telefónica Digital ________________________________ Este mensaje se dirige exclusivamente a su destinatario. Puede consultar nuestra política de envío y recepción de correo electrónico en el enlace situado más abajo. This message is intended exclusively for its addressee. We only send and receive email on the basis of the terms set out at: http://www.tid.es/ES/PAGINAS/disclaimer.aspx
On 04/09/2013 08:15, Joaquín Mª López Muñoz wrote:
Use index #0:
auto range = data.get< 0 >().equal_range( someTypePtr );
Ah yes, indeed, thank you !
In fact, you can get rid of index #2: when using a composite key you can search by providing only the first m fields of the key, so for all practical purposes index #2 is redundant with #0.
With #2 I can erase by doing : units_.get< 2 >().erase( &publisher ); With #0 it seems I need to do : auto range = units_.equal_range( &publisher ); units_.erase( range.first, range.second ); Or is there a shorter way ? Also if my use case rarely uses #0 but uses #1 a lot (for instance #0 is for adding/erasing while #1 is used to perform some operations very often), would it be more efficient to invert the indices or is it just a matter of whichever is the more convenient to write ? Many thanks ! MAT.
El 04/09/2013 9:41, Mathieu Champlon escribió:
On 04/09/2013 08:15, Joaquín Mª López Muñoz wrote:
In fact, you can get rid of index #2: when using a composite key you can search by providing only the first m fields of the key, so for all practical purposes index #2 is redundant with #0.
With #2 I can erase by doing :
units_.get< 2 >().erase( &publisher );
With #0 it seems I need to do :
auto range = units_.equal_range( &publisher ); units_.erase( range.first, range.second );
Or is there a shorter way ?
Well, erase is the only lookup function where you can't provide a partial specification of the composite key, so you have to do it as you write above.
Also if my use case rarely uses #0 but uses #1 a lot (for instance #0 is for adding/erasing while #1 is used to perform some operations very often), would it be more efficient to invert the indices or is it just a matter of whichever is the more convenient to write ?
Efficiency is not affected, it's just a matter of convenience (#index 0 can be used directly without using get<0>().) (In reality, efficiency can be affected, but probably in a negligible way: when inserting an element, Boost.MultiIndex inserts it first in index #0, then in #1, etc., and if some index fails (because of unicity constraints), previous insertions are undone. So, if index A is more likely to ban insertions than index B, it potentially pays off to have index A at a lower position than B.) Joaquín M López Muñoz Telefónica Digital ________________________________ Este mensaje se dirige exclusivamente a su destinatario. Puede consultar nuestra política de envío y recepción de correo electrónico en el enlace situado más abajo. This message is intended exclusively for its addressee. We only send and receive email on the basis of the terms set out at: http://www.tid.es/ES/PAGINAS/disclaimer.aspx
participants (2)
-
Joaquín Mª López Muñoz
-
Mathieu Champlon