Search code examples
c++boostdictionaryboost-bimap

Insert into boost::BIMAP using BOOST::associative property map ... failed


With reference to my previously asked question about boost::bimaps and boost associative property maps interface here, I want to use Put and Get helper functions for my bimap.

With reference to a sample code given here, I tried to add the following and i get a long compile error for assertion failed ... Here is the code :

#include <boost/bimap.hpp> 
#include <boost/property_map/property_map.hpp> 
#include <boost/bimap/property_map/set_support.hpp>
#include <iostream> 

using namespace boost; 

int main() 
{
  typedef int vertex_descriptor_t;
  typedef boost::bimaps::bimap< vertex_descriptor_t, size_t > vd_idx_bimap_t;
  typedef boost::associative_property_map<vd_idx_bimap_t::left_map>   asso_vd_idx_bimap_t;

  // define bimap
  vd_idx_bimap_t        my_bimap;
  asso_vd_idx_bimap_t   my_asso_bimap(my_bimap.left);

  typedef typename vd_idx_bimap_t::value_type value_type;    
  my_bimap.insert( value_type( 1, 100 ) );
  // print bimap
  for(auto t = my_bimap.left.begin(); t != my_bimap.left.end(); ++t)
      std::cout << t->first << " " << t->second <<  "\n";

  int z = 1;
  std::cout << "value = " << get ( my_bimap.left, z ) << std::endl;    // prints correctly value = 100


  // ERROR here . 
  boost::put( my_asso_bimap, 2, 19 );

 } 

It gives error as: ( a long list. but i have just put a snippet )

  cannot convert âboost::bimaps::detail::non_mutable_data_unique_map_view_access<Derived, Tag, BimapType>::operator[](const CompatibleKey&)::BIMAP_STATIC_ERROR__OPERATOR_BRACKET_IS_NOT_SUPPORTED360::assert_arg<long unsigned int>()â (type âmpl_::failed************ (boost::bimaps::detai

There is also one error which gives me error at line number 364 of the file (property_map.hpp) in boost

  put(const put_get_helper<Reference, PropertyMap>& pa, K k, const V& v)
 {
   static_cast<const PropertyMap&>(pa)[k] = v;
  }

I understand the error that associative map cannot mutate the data as it references to the left map view . but How do I use put and get helper functions ?

I can use GET (my_bimap.left, z ) functions, but I am not able to use PUT function. I wanted to use associative property map for get and put functions to operate on actual bimap so that i dont have to use insert( value_type() )...

I hope I am clear enough for my problem. Please suggest.


Solution

  • In general you cannot update bimap entries via iterators:

    The relations stored in the Bimap will not be in most cases modifiable directly by iterators because both sides are used as keys of key-based sets. When a bimap left view iterator is dereferenced the return type is signature-compatible with a std::pair< const A, const B >.

    So there's your answer. Likewise, you couldn't

    my_bimap.left[2] = 19;
    

    http://www.boost.org/doc/libs/release/libs/bimap/doc/html/boost_bimap/the_tutorial/differences_with_standard_maps.html#boost_bimap.the_tutorial.differences_with_standard_maps.iterator__value_type

    Now, reading a bit more on there leads me to "suspect" the following solution:

    typedef bm::bimap< vertex_descriptor_t, bm::list_of<size_t> > vd_idx_bimap_t;
    

    Disclaimer: I don't know about the semantics that this changes (?) but it at least appears to support writable references. The below sample prints

    1 100
    value = 100
    1 100
    2 42
    

    See it Live On Coliru


    Full Listing

    #include <boost/bimap.hpp> 
    #include <boost/property_map/property_map.hpp> 
    #include <boost/bimap/property_map/set_support.hpp>
    #include <boost/bimap/list_of.hpp>
    #include <iostream> 
    
    using namespace boost; 
    
    int main() 
    {
        typedef int vertex_descriptor_t;
        namespace bm = boost::bimaps;
        typedef bm::bimap< vertex_descriptor_t, bm::list_of<size_t> > vd_idx_bimap_t;
        typedef boost::associative_property_map<vd_idx_bimap_t::left_map>   asso_vd_idx_bimap_t;
    
        // define bimap
        vd_idx_bimap_t        my_bimap;
        asso_vd_idx_bimap_t   my_asso_bimap(my_bimap.left);
    
        typedef typename vd_idx_bimap_t::value_type value_type;    
        my_bimap.insert( value_type( 1, 100 ) );
    
        // print bimap
        for(auto t = my_bimap.left.begin(); t != my_bimap.left.end(); ++t)
            std::cout << t->first << " " << t->second <<  "\n";
    
        int z = 1;
        std::cout << "value = " << get ( my_bimap.left, z ) << std::endl;    // prints correctly value = 100
    
        boost::put( my_asso_bimap, 2, 42 );
    
        for(auto t = my_bimap.left.begin(); t != my_bimap.left.end(); ++t)
            std::cout << t->first << " " << t->second <<  "\n";
     }