使用std::bind绑定函数的问题
A problem that using std::bind to bind a function
我无法编译以下c++代码,错误显示在函数call2
中,我想call
和call2
是一样的,但错误发生在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
可以接受这个参数。
我无法编译以下c++代码,错误显示在函数call2
中,我想call
和call2
是一样的,但错误发生在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
可以接受这个参数。