Boost::Bimap equivalent of bidirectional multimap
Asked Answered
S

2

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 ?

Saddleback answered 29/8, 2012 at 9:41 Comment(0)
S
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;
   }
}
Salian answered 29/8, 2012 at 9:54 Comment(0)
T
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
Towns answered 13/4, 2013 at 14:59 Comment(5)
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.Luu
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.Towns
@JavierBravo kudos for updating this answer. However, indeed you completely missed the plot: Live On ColiruTheone
And here's the a simplified version of the equal_range sample: Live On Coliru /cc @Luu 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 :)Theone
@Theone Wow I don't remember this thread at all... Untested: Shouldn't a boost::bimap<bimaps::multiset_of<int>, bimaps::multiset_of<int> > work though? *edit: Read the original question again; "simple" map in one direction was a requirement.Luu

© 2022 - 2024 — McMap. All rights reserved.