c++ - 确保 std::bind 提供正确数量的参数

标签 c++

更改std::function 的签名后,我想知道编译器没有提示我还没有更改的函数签名。

基本上,我的代码如下所示:

#include <functional>
#include <iostream>
#include <vector>

class CallbackCaller
{
public:
    typedef std::function<void (unsigned, int)> CallbackFunction;

    void registerCallbackFunction(CallbackFunction cb_function)
    {
        callback_functions_.push_back(cb_function);
    }

    void callThemAll()
    {
        for (CallbackFunction &cb_function : callback_functions_)
            cb_function(5, -3);
    }

private:
    std::vector<CallbackFunction> callback_functions_;
};

class CallbackHandler
{
public:
    CallbackHandler(CallbackCaller &callback_caller)
    {
        callback_caller.registerCallbackFunction(std::bind(&CallbackHandler::f1, this, std::placeholders::_1)); // !!!
        callback_caller.registerCallbackFunction(std::bind(&CallbackHandler::f2, this, std::placeholders::_1, std::placeholders::_2));
    }

private:
    void f1(unsigned x)
    {
        std::cout << "f1: " << x << std::endl;
    }

    void f2(unsigned x, int y)
    {
        std::cout << "f2: " << x << ", " << y << std::endl;
    }
};

int main()
{
    CallbackCaller callback_caller;
    CallbackHandler callback_handler(callback_caller);
    callback_caller.callThemAll();
    return 0;
}

为什么 registerCallbackFunction 接受 f1,即使它的签名不匹配?有没有办法让这段代码编译失败?

最佳答案

std::bind 没有预知它将存储在期望特定事物的 std::function 中的事实。它只知道给它的成员函数的签名。因此,它需要您绑定(bind) this一个占位符

之后它仅仅提供了一个带有模板化可变函数调用运算符的函数对象。所述函数调用运算符具有接受任意数量的参数的属性,并且不使用任何多余的参数。它不会提示,它会简单地评估然后继续忽略它不需要的东西。同样,它只需要一个参数。

std::function 依次检查它被赋予的仿函数是否可以用 2 个参数调用。模板化函数调用运算符可以做到这一点。它接受第二个参数,然后丢弃它。完全合法。

std::bind 的更好替代方案是通用 lambda:

//callback_caller.registerCallbackFunction([this](auto&& ...x) {f1(std::forward<decltype(x)>(x)...);}); // !!!
callback_caller.registerCallbackFunction([this](auto&& ...x) {f2(std::forward<decltype(x)>(x)...);});

现在进行的类型删除要少得多,提供给 lambda 的参数数量必须与 f1f2 预期的参数数量相匹配,否则会有是一个错误。

自 C++14 以来,std::bind 的用例几乎不存在。

关于c++ - 确保 std::bind 提供正确数量的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51513416/

相关文章:

c++ - 将双常量定义为十六进制?

c++ - boost使用c++11有多好?

c++ - 在 C++ 中使用 UTF-8 std::string 对象

c++ - 对 `TextOutA@20' 的 undefined reference

c++ - 是否所有运算符重载都将运算符放在将调用其重载的对象之后?

c++ - 回想起来,将 'this' 设为引用而不是指针会更好吗?

c++ - 像键盘一样向 cpu 发送中断?

c++ - 类型删除、委托(delegate)和 lambda 函数与 msvc

c++ - 如何使用 FFMPEG sws_scaler api 从 AV_PIX_FMT_VAAPI 转换为 AV_PIX_FMT_YUV420?

c++ - 使用 CMake 构建时缺少依赖项