0

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> > > >)'
Abruzzo Forte e Gentile
  • 14,423
  • 28
  • 99
  • 173
  • Could you specify your compiler version, please? Some older compilers which don't understand partial specialization can't accept a pointer-to-function-member as the first argument to `boost::bind`. – Dan Hulme Mar 08 '12 at 18:23

2 Answers2

1

http://www.boost.org/doc/libs/1_49_0/libs/bind/bind.html#Troubleshooting suggests that you can sometimes work around problems with overloaded functions by casting the pointer-to-member-function to the desired type. Using a temporary variable to stop it becoming completely unreadable, it would look like:

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

typename dict_type::value_type to_insert(key,value);

out_type (dict_type::*ins) (typename dict_type::value_type const&) const = &dict_type::insert;

boost::function<void()> f = boost::bind(
    ins
    ,obj_
    ,boost::cref(to_insert)
);
Dan Hulme
  • 14,779
  • 3
  • 46
  • 95
1

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);};
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Am I wrong to say that your solution uses a static_cast<> is faster? By using static_cast<> the ambiguity is resolved at compile time so even if it is more long to write it makes the call to bind quicker, isn'it? – Abruzzo Forte e Gentile Mar 08 '12 at 19:55
  • In theory the `static_cast` will be faster (it's equivalent to my example), but some compilers might be able to optimize out the trivial function, so they may both turn out to give the same result. – Dan Hulme Mar 08 '12 at 20:05
  • Auch..I found it..it should be &obj as second argument – Abruzzo Forte e Gentile Mar 09 '12 at 11:00