如何绑定重载函数

◆ 问题

环境: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

上一篇:mtk 配置pmic打开电压端口


下一篇:【转载】可调用对象包装器、绑定器