0

I want to access all the keys of a repeated element in bimap. I have some example code below

#include <string>
#include <iostream>
#include <utility>
#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/multiset_of.hpp>

namespace bimaps = boost::bimaps;
typedef boost::bimap<bimaps::set_of<unsigned long int>,
        bimaps::multiset_of<unsigned long int > > bimap_reference;
typedef bimap_reference::value_type position;
bimap_reference numbers;

int main()
{
    numbers.insert(position(123456, 100000));
    numbers.insert(position(234567, 80000));
    numbers.insert(position(345678, 100000));
    numbers.insert(position(456789, 80000));


    auto it = numbers.right.find(100000);
    std::cout<<"numbers:"<<it->first<<"<->"<<it->second<<std::endl;
    return 0;
}

In the above code I have repeated elements on right side. The above code give me the first key of the element 100000, i,e 123456 <--> 100000. But I have one more entry of the element 100000, how to access all the keys of the repeated element (the element may be present multiple times with unique key on left side).

AwaitedOne
  • 992
  • 3
  • 19
  • 42

1 Answers1

2

Use multiset::equal_range on the right hand side.

In this way you get an iterator range from the first occurrence to the last which you need to then iterate.

using ritr = bimap_reference::right_const_iterator;

std::pair<ritr, ritr> range = numbers.right.equal_range(100000);

for (auto itr = range.first; itr != range.second; ++itr)
{
        ...
}


Edit:

The using ritr statement makes ritr an alias for the actual type. It's equivalent to a typedef which you use higher up.

The alias simply makes the next line easier to read than had I typed-out the actual type name twice in the std::pair declaration.

Even an easier solution will be to use auto.

The equal_range is a member function of the multiset which is on the right of the bimap. It returns a std::pair which contains the begin and end iterators of elements in the multiset that equal the specified key, for you to iterate in the normal way.

Cfir TSabari
  • 372
  • 3
  • 13
acraig5075
  • 10,588
  • 3
  • 31
  • 50
  • Thanks for your answer, but it gives only the first location. http://cpp.sh/8j74i – AwaitedOne Feb 02 '17 at 09:39
  • I should get both the keys for `100000` i,e `123456<--> 100000` and `345678<-->100000`, in the above code I get only `123456<--> 100000` that is the first location. – AwaitedOne Feb 02 '17 at 09:50
  • No, your online code example doesn't have the duplicates. You have a typo. Fix the typo, and you'll see it gives both locations. – acraig5075 Feb 02 '17 at 09:50
  • Actually I want to make sure if the element is there. If the element is not there then the range will point to the end of the `bimap` for that I tried `if(auto itr != numbers.right.end()){....}else{...........}`, but `error: expected primary-expression before auto` – AwaitedOne Feb 03 '17 at 07:35
  • Lose the `auto`. You don't want that in the `if` statement, it's a syntax error. Just have `if (itr != numbers.right.end())` – acraig5075 Feb 03 '17 at 07:41
  • `error: ‘itr’ was not declared in this scope`, I am trying before `for (auto itr = range.first; itr != range.second, ++itr){ ...}` – AwaitedOne Feb 03 '17 at 07:44
  • First the declaration. `auto itr = range.first;` Second use it (don't redeclare it) to test for end condition. `if (itr != numbers.right.end())`. Third, reuse it again (don't redeclare it) in the loop `for (itr = range.first; itr != range.second; ++itr)` – acraig5075 Feb 03 '17 at 07:57