我正在尝试使用map
将std::for_each and boost::bind
的所有密钥复制到另一个密钥中。
我收到编译错误
error: no matching function for call to
‘bind(<unresolved overloaded function type>, boost::arg<1>&, boost::arg<1>&)’
在我的代码下面。
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)));
你知道出了什么问题吗?
答案 0 :(得分:3)
关键问题是你无法获取重载集的地址:std::make_pair
是一个函数模板,你甚至不会说明你正在谈论的实例。同样地,std::map<K, V>::insert
被重载,例如,版本采用一个元素,版本采用范围。
即使您可以以某种形式获取重载功能的地址,但如果您可以帮助它,您实际上并不是真的想要它!原因是通过函数指针或成员函数指针调用比调用inline
函数要昂贵得多,并且通过函数指针调用更难以内联:编译器必须证明某个特定的[成员]函数指针总是指相同的[member]函数。
这两个问题的解决方案是给bind()
一个带有模板化函数调用操作符的函数对象,该操作符只是委托给相应的函数。例如:
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));
}
};
使用C ++ 03时,您使用T0 const&
和T1 const&
代替T0&&
和T1&&
,而您只需传递参数使用std::forward<>()
。在C ++ 11设置中,您可能宁愿使用decltype()
返回类型。用于插入的类似函数对象可能如下所示:
struct inserter {
template <typename M, typename T>
void operator()(M* map, T&& value) {
map->insert(std::forward<T>(value));
}
};
使用这两个功能对象,您可以使用bind()
表达式:
std::for_each(A.begin(), A.end(),
boost::bind(inserter(), &B, boost::bind(make_a_pair(), _1, _1)));
现在我无法轻易地对此进行测试,但这些内容应该有效,假设_1
和_1
成对是理想的。看来,你真的想要创建一个从键到键的映射,在这种情况下你需要适当地投影原始地图的键,例如,使用另一个函数对象:
struct project1st {
template <typename T0, typename T1>
typename std::remove_const<T0>::type
operator()(std::pair<T0, T1> const& p) const {
return p.first;
}
};
此功能对象从第一个const
中移除T0
,如果有的话(如果该对来自std::map<K, V>
,则该对将属于std::pair<K const, V>
类型)返回结果。您可以使用此函数对象将每个_1
替换为合适的std::bind()
表达式,即使用
boost::bind(project1st(), _1)