Reputation: 14869
I am trying to copy all of the keys of a map
into another by using std::for_each and boost::bind
.
I am getting compile error saying
error: no matching function for call to
‘bind(<unresolved overloaded function type>, boost::arg<1>&, boost::arg<1>&)’
Below my code.
using namespace boost;
map<string,int32_t> A;
typedef map<string,string> BType;
BType B;
std::for_each(A.begin(), A.end(),
bind(&BType::insert,&B,bind(&std::make_pair,_1,_1)));
Do you know what is wrong?
Upvotes: 0
Views: 931
Reputation: 153840
The key problem is that you can't take the address of an overload set: std::make_pair
is a function template and you don't even state what instantiation(s) you are talking about. Likewise std::map<K, V>::insert
is overloaded, e.g., with a version taking one element and a version taking a range.
Even if you could take the address of an overloaded function in some form, you actually don't really want to if you can help it! The reason is that calling through a function pointer or a member function pointer is a lot more expensive than calling an inline
function and calls through function pointers are much harder to inline: the compiler has to proof that a particular [member] function pointer always refers to the same [member] function.
The solution to both problems is to give bind()
a function object with a templated function call operator which simply delegates to the appropriate function. For example:
struct make_a_pair {
template <typename T0, typename T1>
std::pair<T0, T1> operator()(T0&& t0, T1&& t1) {
return std::make_pair(std::forward<T0>(t0), std::forward<T1>(t1));
}
};
When using C++03 you'd use T0 const&
and T1 const&
instead of T0&&
and T1&&
and you'd just pass the arguments instead of using std::forward<>()
. In a C++11 setting you'd probably rather return a type using decltype()
. A similar function object for inserting could look like this:
struct inserter {
template <typename M, typename T>
void operator()(M* map, T&& value) {
map->insert(std::forward<T>(value));
}
};
With these two function objects in place you could use your bind()
expressions:
std::for_each(A.begin(), A.end(),
boost::bind(inserter(), &B, boost::bind(make_a_pair(), _1, _1)));
Right now I can't quite test this easily but something along those lines should work, assuming pairs of _1
and _1
are what is desired. It seems, you really want to create a mapping from the key to the key in which case you'd need to appropriately project the keys of the original map, e.g., using another function object:
struct project1st {
template <typename T0, typename T1>
typename std::remove_const<T0>::type
operator()(std::pair<T0, T1> const& p) const {
return p.first;
}
};
This function object removes a const
from the first T0
if there is any (if the pair is from a std::map<K, V>
the pair will be of type std::pair<K const, V>
) before returning the result. You'd replace each _1
with a suitable std::bind()
expression using this function object, i.e., with
boost::bind(project1st(), _1)
Upvotes: 3