使用bind和make_pair进行未解决的重载

时间:2013-12-12 12:37:32

标签: c++ stl boost-bind

我正在尝试使用mapstd::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)));

你知道出了什么问题吗?

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)