◆ 问题
环境:macOS Mojave (版本10.14.6), clang-1001.0.46.4 (-std=c++11)
代码中存在重载(overloaded)的*函数(也称全局函数)或类成员函数,当开发者尝试用 std::bind 绑定其中一个时,会提示如下编译错误:
error: no matching function for call to 'bind'
std::bind
^~~~~~~~~
note: candidate template ignored: couldn't infer template argument '_Fp'
bind(_Fp&& \__f, _BoundArgs&&... \__bound_args)
^
note: candidate template ignored: couldn't infer template argument '_Rp'
bind(_Fp&& \__f, _BoundArgs&&... \__bound_args)
^
◆ 示例
有两个重载的 shoot *函数(#1,#2),两个重载的类成员函数 Archer::shoot(#3,#4),
void shoot() { // #1
std::printf("\n\t[Free Function] Let an arrow fly... Hit!\n");
}
bool shoot(unsigned n) { // #2
std::printf("\n\t[Free Function] Let %d arrows fly... All missed!\n", n);
return false;
}
class Archer {
public:
void shoot() { // #3
std::printf("\n\t[Member Function] Let an arrow fly... Missed!\n");
}
bool shoot(unsigned n) { // #4
std::printf("\n\t[Member Function] Let %d arrows fly... All hit!\n", n);
return true;
}
};
开发者希望绑定一个*函数(#2)或一个类成员函数(#4)时,
// bind #2
std::bind(shoot, 3)();
Archer hoyt;
// bind #4
std::bind(&Archer::shoot, &hoyt, 3)();
编译该代码时会抛出前述编译错误。
◆ 原因
重载函数的函数签名(signature)不同,是不同的函数。当开发者想绑定一个重载函数而仅给出名字时,编译器无法判定希望绑定的是哪一个函数,就会抛出编译错误。
◆ 解法
在绑定重载函数时,给出重载函数的签名。
方法一,把函数签名作为类型参数传给 std::bind 函数,
// std::bind<Signature>(Function, Args...);
// example:
std::bind<bool(*)(unsigned)>(shoot, 3);
方法二,把函数签名作为类型参数传给 static_cast,再将转型后的函数对象(Function Object)传给 std::bind 函数,
// std::bind(static_cast<Signature>(Function), Args...);
// example:
std::bind(static_cast<bool(Archer::*)(unsigned)>(&Archer::shoot), &hoyt, 5);
◆ 附录
完整示例 how_to_bind_an_overloaded_funtion.cpp 。