mfo*_*ini 21 c++ bind function c++11
我在检测为什么这不是编译时遇到了麻烦.我有一些std::function基于某些参数返回的lambda函数.
我已经将我的问题缩小到这个片段(它不使用lambdas,但完全重现了我的错误):
#include <functional>
#include <iostream>
struct foo {
template<class T>
void bar(T data) {
std::cout << data << "\n";
}
};
void some_fun(const std::function<void(int)> &f) {
f(12);
}
int main() {
foo x;
auto f = std::bind(&foo::bar<int>, x, std::placeholders::_1);
auto w = std::bind(some_fun, f);
w();
}
Run Code Online (Sandbox Code Playgroud)
调用w()产生一个可爱的gcc错误输出,其中我无法弄清楚出了什么问题.这是gcc 4.6.1回应的错误:
g++ -std=c++0x test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:20:7: error: no match for call to ‘(std::_Bind<void (*(std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>))(const std::function<void(int)>&)>) ()’
/usr/include/c++/4.6/functional:1130:11: note: candidates are:
/usr/include/c++/4.6/functional:1201:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1215:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1229:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1243:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
Run Code Online (Sandbox Code Playgroud)
这里f应该是一些可调用的对象,它将int作为参数并x.bar(int)使用它进行调用.在另一方面,w仅仅是一个可调用对象它调用some_fun(f),作为f上述的可调用的对象,它具有由所期望的签名some_fun的参数.
我错过了什么吗?我可能不知道如何实际混合std::bind和 std::function.
Man*_*agu 21
std::bind表达式和它们的boost::bind前辈一样,支持一种组合操作.你的表达w大致相当于
auto w=std::bind(some_fun, std::bind(&foo::bar<int>, x, std::placeholders::_1) );
Run Code Online (Sandbox Code Playgroud)
以这种方式嵌套绑定被解释为
x.bar<int>(y)where 值y是传递给结果函子的第一个参数.some_fun.但是x.bar<int>(y)返回void,而不是任何函数类型.这就是为什么这不编译.
正如K-ballo指出的那样boost::bind,你可以解决这个问题boost::protect.正如Kerrek SB和ildjarn指出的那样,解决这个问题的一个方法是:不要使用autofor f.您不希望f拥有绑定表达式的类型.如果f有其他类型,则std::bind不会尝试应用函数组合规则.例如,您可以提供f以下类型std::function<void(int)>:
std::function<void(int)> f = std::bind(&foo::bar<int>, x, std::placeholders::_1);
auto w = std::bind(some_fun, f);
Run Code Online (Sandbox Code Playgroud)
由于f字面上没有绑定表达式的类型,因此在类型std::is_bind_expression<>::value上将为false f,因此std::bind第二行中的表达式将仅按字母顺序传递值,而不是尝试应用函数组合规则.