Search code examples
c++boost-bindboost-function

boost::bind and insert of a boost::unordered_map


I want to use boost::bind to create a boost::function inserting a new key-value pair into a boost::unoredered_map but I got few compilation errors.

typedef boost::unordered_map< 
        std::string, std::string > dict_type;


inline void insert( const std::string& key, const std::string& value ){

    typedef std::pair<dict_type::iterator, bool> out_type;

    dict_type::value_type to_insert(key,value);

    boost::function<void()> f = boost::bind<out_type>( 
        &dict_type::insert
        ,obj_
        ,boost::cref(to_insert)
    );
}

The error below looks like bind cannot find the right overload for unordered_map::insert. In this case I specify exactly the right overload but this time it doesn't work. Do you know what it is?

 ../include2/llve_clorder_id.h:32: error: no matching function for call to 
'bind(<unresolved overloaded function type>,
 boost::unordered_map<std::basic_string<char, std::char_traits<char>, 
 std::allocator<char> >, std::basic_string<char, std::char_traits<char>, 
 std::allocator<char> >, boost::hash<std::basic_string<char, std::char_traits<char>,   
 std::allocator<char> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, 
 std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, 
 std::char_traits<char>, std::allocator<char> >, std::basic_string<char, 
 std::char_traits<char>, std::allocator<char> > > > >&, const 
 boost::reference_wrapper<const std::pair<const std::basic_string<char, 
 std::char_traits<char>, std::allocator<char> >, std::basic_string<char, 
 std::char_traits<char>, std::allocator<char> > > >)'

Solution

  • The problem is that boost::unordered_map contains more than one insert, so &dict_type::insert is ambiguous. The simplest solution is to define a function to call the correct overload:

    void insert(dict_type & dict, dict_type::value_type const & value) {
        dict.insert(value);
    }
    
    boost::function<void()> f = boost::bind( 
        insert
        ,boost::ref(obj_)
        ,boost::cref(to_insert)
    );
    

    or you could specify the overload explicitly:

    boost::function<void()> f = boost::bind( 
        static_cast<out_type (dict_type::*)(dict_type::value_type const &)>(&dict_type::insert)
        ,obj_
        ,boost::cref(to_insert)
    );
    

    In C++11, you can avoid the problem with a lambda:

    std::function<void()> f = [&](){obj_.insert(to_insert);};