我'm having trouble in detecting why the heck is this not compiling. I'得到了一些基于某个参数返回 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();
}
对 w()
的调用产生了一个可爱的gcc错误输出,其中我可以't figure out what'出错了 . 这是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>)>}]
这里, f
应该是一个可调用的对象,它以int作为参数并使用它调用 x.bar(int)
. 另一方面, w
只是一个可调用的对象,它调用 some_fun(f)
,是 f
上面提到的可调用对象,它具有 some_fun
参数所期望的签名 .
我错过了什么吗?我可能不知道如何实际混合 std::bind
和 std::function
.
2 回答
std::bind表达式,就像它们的
boost::bind
前辈一样,支持一种合成操作 . 您对w
的表达式大致相当于以这种方式嵌套绑定被解释为
计算
x.bar<int>(y)
的值,其中y
是传递给结果仿函数的第一个参数 .将结果传递给
some_fun
.但是
x.bar<int>(y)
返回void,而不是任何函数类型 . 那's why this doesn'编译 .正如K-ballo指出的那样,使用
boost::bind
,您可以使用boost::protect
解决此问题 . 正如Kerrek SB和ildjarn指出的那样,解决这个问题的方法之一是:不要将auto
用于f
. 您不希望f
具有绑定表达式的类型 . 如果f
具有其他类型,则std::bind
将不会尝试应用函数组合规则 . 例如,您可以给f
类型std::function<void(int)>
:由于
f
实际上没有绑定表达式的类型,std::is_bind_expression<>::value
在f
的类型上将为false,因此第二行中的std::bind
表达式将只传递逐字的值,而不是尝试应用函数组合规则 .some_fun
想要const std::function<void(int)> &
类型的参数 .std :: bind返回“未指定类型T的函数对象”(查看提供的链接,“返回值”部分),您试图将其作为some_fun参数传递 .
这似乎会导致问题,因为这种参数类型不是预期的 .
看看:http://en.cppreference.com/w/cpp/utility/functional/bind