20

First part of the question is that I am trying to use boost::bimap, but from the documentation it is unclear to me how to define a bidirectional multimap.

The second part of the question is that I need it to be a map in one direction and a multimap in the other direction, can this be done using boost::bimap ?

Has anyone experience of this or can point me to the correct page ?

BlueTrin
  • 9,610
  • 12
  • 49
  • 78

2 Answers2

18

All is in documentation... http://www.boost.org/doc/libs/1_51_0/libs/bimap/doc/html/boost_bimap/the_tutorial/discovering_the_bimap_framework.html

typedef boost::bimap<bimaps::multiset_of<int>, bimaps::set_of<int>> bimap_t;

Example.

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

namespace bimaps = boost::bimaps;

int main()
{
   typedef boost::bimap<bimaps::multiset_of<int>, bimaps::set_of<int>> bimap_t;
   typedef bimap_t::value_type value_type;
   bimap_t bimap;
   bimap.insert(value_type(1, 1));
   bimap.insert(value_type(1, 2));
   auto& left = bimap.left;
   auto it = left.find(1);
   std::cout << "LEFT" << std::endl;
   for (; it != left.end(); ++it)
   {
      std::cout << it->first <<  " " << it->second << std::endl;
   }
   auto& right = bimap.right;
   auto r_it = right.find(2);
   std::cout << "RIGHT" << std::endl;
   for (; r_it != right.end(); ++r_it)
   {
      std::cout << r_it->first << " " << r_it->second << std::endl;
   }
}
Community
  • 1
  • 1
ForEveR
  • 55,233
  • 2
  • 119
  • 133
12

The answer from ForEverR is partially correct for the first part of your question (how to define a bidirectional multimap?).

For the second part (accessing a bimap which is a map in one direction and a multimap in the other direction) It is not correct.

A correct way to access would be [ http://rextester.com/BXBDHN12336 ]:

//bimap operations

#include <boost/bimap.hpp>
#include <boost/bimap/set_of.hpp>
#include <boost/bimap/multiset_of.hpp>

int main()
{
   typedef boost::bimap<boost::bimaps::multiset_of<int>, boost::bimaps::set_of<int>> bimap_t;
   typedef bimap_t::value_type value_type;
   bimap_t bimap;
   bimap.insert(value_type(1, 1));
   bimap.insert(value_type(10, 50)); 
   bimap.insert(value_type(1, 2));
   bimap.insert(value_type(9, 15));   

   typedef bimap_t::left_const_iterator l_itr_t;
   typedef std::pair<l_itr_t,l_itr_t> l_itr_range_t;

   l_itr_range_t ii = bimap.left.equal_range(1);

   std::cout << "LEFT" << std::endl;        
   for(l_itr_t it = ii.first; it != ii.second; ++it)
   {
     std::cout << "Key = " << it->first << "    Value = " << it->second << std::endl;
   }  

   std::cout << "RIGHT" << std::endl;
   std::cout << "Key = " << 1 << "    Value = " << bimap.right.at(1) << std::endl;
}

stdout:
LEFT
Key = 1    Value = 1
Key = 1    Value = 2
RIGHT
Key = 1    Value = 1

The example from ForEverR 'seems' to work because of the order of the data inserted but check out the results when you insert another couple at the end bimap.insert(value_type(9, 15));:

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

namespace bimaps = boost::bimaps;

int main()
{
   typedef boost::bimap<bimaps::multiset_of<int>, bimaps::set_of<int>> bimap_t;
   typedef bimap_t::value_type value_type;
   bimap_t bimap;
   bimap.insert(value_type(1, 1));
   bimap.insert(value_type(1, 2));
   bimap.insert(value_type(9, 15));
   auto& left = bimap.left;
   auto it = left.find(1);
   std::cout << "LEFT" << std::endl;
   for (; it != left.end(); ++it)
   {
      std::cout << it->first <<  " " << it->second << std::endl;
   }
   auto& right = bimap.right;
   auto r_it = right.find(2);
   std::cout << "RIGHT" << std::endl;
   for (; r_it != right.end(); ++r_it)
   {
      std::cout << r_it->first << " " << r_it->second << std::endl;
   }
}

stdout: 
LEFT
1 1
1 2
9 15
RIGHT
2 1
15 9
Javier Bravo
  • 163
  • 1
  • 7
  • 1
    I'm not sure what you mean with "seems to work". The output you're getting is because it & r_it are initialized to somewhere in the middle of the multimap with find(). If initialized with begin(), all three pairs print properly. – namezero Feb 14 '14 at 20:13
  • 1
    Yes, but the point here is not to print the three pairs. The point is to access the bimap (from the left and/or from the right) and retrieve the pairs for a given key. I have edited my response including an example where you can fulfill this by using equal_range. I hope this helps. – Javier Bravo Nov 24 '14 at 21:39
  • @JavierBravo kudos for updating this answer. However, indeed you completely missed the plot: **[Live On Coliru](http://coliru.stacked-crooked.com/a/39ddf19cff3e97d8)** – sehe Nov 24 '14 at 21:39
  • 2
    And here's the a simplified version of the equal_range sample: **[Live On Coliru](http://coliru.stacked-crooked.com/a/cf9bccc3de10975d)** /cc @namezero I think we can consider that you botched the iterator handling, and even didn't see the eror in over a year enough reason to appreciate why keeping the complexity out of the call sites is important :) – sehe Nov 24 '14 at 21:44
  • @sehe Wow I don't remember this thread at all... Untested: Shouldn't a boost::bimap, bimaps::multiset_of > work though? *edit: Read the original question again; "simple" map in one direction was a requirement. – namezero Nov 28 '14 at 21:32