使用std::bind绑定函数的问题

A problem that using std::bind to bind a function

我无法编译以下c++代码,错误显示在函数call2中,我想callcall2是一样的,但错误发生在call2上。我将错误信息粘贴到相关代码行。任何人都可以帮助我解释执行 std::bind 后 f 的签名到底是什么?我还提供了 call3,它使用 beast::bind_front_handler 来绑定函数,并且编译没有错误。

顺便说一句:我的编译器符合 c++ 标准 14。 谢谢你的时间。

#include <boost/beast.hpp>
#include <iostream>
#include <string>

namespace beast = boost::beast;

void subfunc(int a) { std::cout << "a=" << a << std::endl; }

void func(int n, std::string s, std::function<void(int)> &&subf) { subf(n); }

template <typename F>
void call(F &&f2) {
  auto f = std::bind(func, 1, "100", std::forward<F>(f2));
  f();
}

void call2(std::function<void(int)> &&f2) {
  auto f = std::bind(func, 1, "100", std::move(f2));
  f(); // No matching function for call to object of type 'std::__1::__bind<void (&)(int, std::__1::basic_string<char>, std::__1::function<void (int)> &&), int, char const (&)[4], std::__1::function<void (int)> >'
}

void call3(std::function<void(int)> &&f2) {
  auto f = beast::bind_front_handler(func, 1, "100", std::move(f2));
  f();
}

int main() {
  call(subfunc);
  call2(subfunc);
  call3(subfunc);
  return 0;
}

左值不能绑定到右值引用

当你有:

void bar(int&&) {}
int i = 0;
bar(i);                // error

最后一行无法编译。

这就是您的代码在第二种情况下失败的原因。


std::bind 将所有传递的参数 copies/moves 放入新生成的仿函数的数据成员中:

std::bind(func,arg1,arg2)

给你:

class closure1 {
    Arg1 arg1;
    Arg2 arg2;

    void operator()() {
         func(arg1,arg2);
    }
};

它还提供函数调用运算符,其中 arg(s) 作为 Lvalues 按值传递(成员函数运算符中的第 4 个点() std::bind reference 部分:

Otherwise, the ordinary stored argument arg is passed to the invokable object as lvalue argument: the argument vn in the std::invoke call above is simply arg and the corresponding type Vn is T cv &, where cv is the same cv-qualification as that of g.

所以这个:

auto f = std::bind(func, 1, "100", std::forward<F>(f2));

生成

class closure2 {
       int i = 1;
       std::string s = "100";
       std::forward<void(int)> f;
       void operator()() {
             func(i,s,f);    // [1]
       }
};

and in [1] 是问题,因为 f as lvalue cannot be bound to rvalue reference declared in:

void func(int n, std::string s, std::function<void(int)> &&subf)

您可以添加另一个采用 左值引用:

的重载
void func2(int n, std::string s, std::function<void(int)> &subf)

并使用该版本的重载调用 bind


bind_front_handler 没有问题,因为在此实现中,生成的仿函数的所有数据成员都被转发到目标:

 func(...,std::forward< std::function<void()> >(f));

所以f将被转换为右值引用,并且func可以接受这个参数。


Demo