重载函数绑定的编译错误

本文描述了在绑定重载函数时出现的一个编译问题,并在解释其原因后给出了对应的解决办法。

◆ 问题

代码中存在重载(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,再将转型后的结果传给 std::bind 函数,

// std::bind(static_cast<Signature>(Function), Args...); 
// example:
std::bind(static_cast<bool(Archer::*)(unsigned)>(&Archer::shoot), &hoyt, 5);

◆ 最后

完整的代码请参考 [gitee] cnblogs/15572214

posted @ 2021-11-26 14:20  green-cnblogs  阅读(380)  评论(0编辑  收藏  举报