下列:
#include <functional> struct Foo { void bar1() {} void bar2(int) {} void bar3(int,int) {} void bar4(int,int,int) {} }; int main() { Foo foo; auto f1 = std::bind(&Foo::bar1,&foo); auto f2 = std::bind(&Foo::bar2,&foo); auto f3 = std::bind(&Foo::bar3,&foo); auto f4 = std::bind(&Foo::bar4,&foo); f1(1,2,3,4); // success f2(1,3); // error f3(1,2); // error f4(1); // error return 0; }
f1(1,4)编译并执行bar1(). f2(1,3),不编译,f3(1,2)不编译(但bar3有正确的原型)和f4(1)不编译.对于这3种情况,Visual Studio 2013中出现的错误是
“类没有将”operator()“或用户定义的转换运算符定义为需要适当数量的参数的”指向函数“或”引用到函数“
我对模板和标准库的理解有限,但这对我来说似乎没有任何逻辑意义.有一个相当简单的解释吗?
解决方法
要将参数传递给目标,您需要在bind表达式中提供这些参数,或者通过向bind表达式添加占位符来保留它们的绑定,然后您必须调用带有参数的函数替换占位符.
你可以调用bar1没有占位符,因为它没有任何参数,所以你不需要传递任何东西.您传递给f1的参数只是被忽略,因为没有未绑定的参数,即没有占位符需要替换.
其他函数需要参数,因此您必须在“绑定时间”处绑定参数,例如.
auto f2a = std::bind(&Foo::bar2,&foo,1); f2a();
auto f2b = std::bind(&Foo::bar2,std::placeholders::_1); f2b(1);
请注意,GCC 5现在有静态断言来捕获这种错误.如果可以确定目标函数的arity,并且绑定表达式对目标函数的每个参数都没有绑定参数或占位符,那么它说:
/usr/local / gcc-head / include / c /5.0.0/functional:1426:7:错误:静态断言失败:指向成员的参数数量错误
你写的是相当于这个,使用lambdas而不是bind:
Foo foo; auto f1 = [&foo](...) { return foo.bar1(); }; auto f2 = [&foo](...) { return foo.bar2(); }; auto f3 = [&foo](...) { return foo.bar3(); }; auto f4 = [&foo](...) { return foo.bar4(); }; f1(1,4); // success f2(1,3); // error f3(1,2); // error f4(1); // error