I'm looking for the optimal solution for retrieving bit-field based objects from multi-index container. For simplicity, the data is:
enum Bit
{
b0 = 1,
b1 = 2,
b2 = 4
};
struct Item
{
int field; // contains Bit values
int info;
};
As far as I know there could be 2 possibilities:
Use a custom predicate in equal_range call (This example is not working because I don't know how to define the predicate):
struct MyTag; using boost::multi_index_container; using namespace boost::multi_index; typedef composite_key<Item, member<Item, int, &Item::field>, member<Item, int, &Item::info> > CompositeKey; typedef hashed_non_unique< tag<MyTag>, CompositeKey> Index1; typedef boost::multi_index_container<Item, indexed_by<Index1> > Container; struct Predicate: public Index1::pred_type { /// what to put here? }; void f() { Item item1 = { int( b0 | b1), 123}; Item item2 = { int( b1 | b2), 123}; Item item3 = { int( b2), 123}; Container c; c.insert( item1); c.insert( item2); c.insert( item3); auto result = c.get<MyTag>().equal_range( boost::make_tuple( int( b2), 123), Index1::hash_type(), Predicate()); for( auto i = result.first; i != result.second; ++i) { std::cout << i->field << ' '; // expect item2 and item3 } }
Add accessors in Item and indexes in multi-index container for each bit from enumeration:
struct Item { int field; int info; bool isB0() const { return ( field & b0) != 0; } bool isB1() const { return ( field & b1) != 0; } bool isB2() const { return ( field & b2) != 0; } }; struct MyTag1; struct MyTag2; struct MyTag3; using boost::multi_index_container; using namespace boost::multi_index; typedef composite_key<Item, const_mem_fun<Item, bool, &Item::isB0>, member<Item, int, &Item::info> > CompositeKeyB0; typedef composite_key<Item, const_mem_fun<Item, bool, &Item::isB1>, member<Item, int, &Item::info> > CompositeKeyB1; typedef composite_key<Item, const_mem_fun<Item, bool, &Item::isB2>, member<Item, int, &Item::info> > CompositeKeyB2; typedef hashed_non_unique< tag<MyTag1>, CompositeKeyB0> Index1; typedef hashed_non_unique< tag<MyTag2>, CompositeKeyB1> Index2; typedef hashed_non_unique< tag<MyTag3>, CompositeKeyB2> Index3; typedef boost::multi_index_container<Item, indexed_by<Index1, Index2, Index3> > Container; void f() { Item item1 = { int( b0 | b1), 123}; Item item2 = { int( b1 | b2), 123}; Item item3 = { int( b2), 123}; Container c; c.insert( item1); c.insert( item2); c.insert( item3); auto result = c.get<MyTag2>().equal_range( boost::make_tuple( true, 123)); for( auto i = result.first; i != result.second; ++i) { std::cout << i->field << ' '; // expect item2 and item3 } }