2

I have a boost::multi_index container. Could anybody tell me how to retrieve a range of iterators based on a certain key? After hours of search I got the idea that lower_bound or upper_bound should do the trick but I still do not got an example. In following example I would like to get all the iterators with price between 22 and 24. Thank you very much.

 struct order                                                      
 {                                                                 
     unsigned int    id;                                           
     unsigned int    quantity;                                     
     double          price;                                        

     order(unsigned int id_, unsigned int quantity_, double price_)
         :id(id_), quantity(quantity_), price(price_){}
}
typedef multi_index_container<                                    
  order,                                                          
  indexed_by<                                                     
    ordered_unique<                                               
      tag<id>,  BOOST_MULTI_INDEX_MEMBER(order, unsigned int, id),
      std::greater<unsigned int>>,                                
    ordered_non_unique<                                           
      tag<price>,BOOST_MULTI_INDEX_MEMBER(order ,double, price)>  
  >                                                               
> order_multi;                                                              
 int main()                                                            
 {                                                                     
     order_multi order_book;                                           

     order_book.insert(order(/*id=*/0, /*quantity=*/10, /*price=*/20));
     order_book.insert(order(/*id=*/1, /*quantity=*/11, /*price=*/21));
     order_book.insert(order(/*id=*/3, /*quantity=*/12, /*price=*/22));
     order_book.insert(order(/*id=*/2, /*quantity=*/1,  /*price=*/22));
    order_book.insert(order(/*id=*/4, /*quantity=*/1,  /*price=*/23));
    order_book.insert(order(/*id=*/5, /*quantity=*/1,  /*price=*/24));
    order_book.insert(order(/*id=*/6, /*quantity=*/1,  /*price=*/24));
    order_book.insert(order(/*id=*/7, /*quantity=*/1,  /*price=*/26));   

  }                                                                                                                                 
loudking
  • 115
  • 4

1 Answers1

4

The range you're after is [lower_bound(22),upper_bound(24)), that is:

auto first=order_book.get<price>().lower_bound(22);
auto last=order_book.get<price>().upper_bound(24);
for(;first!=last;++first)std::cout<<first->id<<" "; // prints 3 2 4 5 6

If you find it confusing to determine when it's lower_ or upper_bound that you need to use, there is a range member function that is probably easier to get right (and marginally faster):

auto range=order_book.get<price>().range(
  [](double p){return p>=22;},  // "left" condition
  [](double p){return p<=24;}); // "right" condition
for(;range.first!=range.second;++range.first)std::cout<<range.first->id<<" ";

provided you use C++11 and have lambda functions. You can also use range in C++03 without native lambda functions, but then you have to resort to Boost.Lambda or else write by hand the functors accepted by range, both of which options are probably too cumbersome.

Joaquín M López Muñoz
  • 5,243
  • 1
  • 15
  • 20
  • Cool. TIL about the `range()` member function. How could I have missed it for so long. I'd use `for (auto& el : boost::make_iterator_range(order_book.get().range(...))) {...}` by the way – sehe May 06 '16 at 20:57
  • can this range function be used with composite key??is there example using composite key..??can it be used to find range with empty solution set?? – ahmed allam Dec 17 '19 at 11:57
  • 1
    Yes, it can. A lower bounder ("left" condition) suitable for use with composite keys would look like `[](const auto& k){return k>=std::tuple(...);}` (and symmetrically for an upper bounder, i.e. the "right" condition). – Joaquín M López Muñoz Dec 17 '19 at 14:18