我在检测为什么这不编译时遇到了麻烦.我有一些基于某个参数返回 std::function
的 lambda 函数.
I'm having trouble in detecting why the heck is this not compiling. I've got some lambda function that returns a std::function
based on some argument.
我已经将我的问题缩小到这个片段(它不使用 lambdas,但完美地重现了我的错误):
I've narrowed down my problem to this snippet(which doesn't use lambdas, but reproduces my error perfectly):
#include <functional>
#include <iostream>
struct foo {
template<class T>
void bar(T data) {
std::cout << data << "
";
}
};
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 错误输出之一,我无法弄清楚出了什么问题.这是 gcc 4.6.1 回显的错误:
The call to w()
produces one of those lovely gcc error outputs in which I can't figure out what's going wrong. This is the error echoed by 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
的参数所期望的签名.
Here, f
should be some callable object which takes an int as argument and calls x.bar(int)
using it. On the other hand, w
is just a callable object which calls some_fun(f)
, being f
the callable object mentioned above, which has the signature expected by some_fun
's parameter.
我错过了什么吗?我可能不知道如何实际混合 std::bind
和 std::function
.
Am I missing something? I probably don't know how to actually mix std::bind
and std::function
.
std::bind
表达式,就像它们的 boost::bind
前辈一样,支持一种组合操作.w
的表达式大致相当于
std::bind
expressions, like their boost::bind
predecessors, support a type of composition operation. Your expression for w
is roughly equivalent to
auto w=std::bind(some_fun, std::bind(&foo::bar<int>, x, std::placeholders::_1) );
这种方式的嵌套绑定被解释为
Nesting binds in this manner is interpreted as
x.bar(y)
的值,其中 y
是传递给结果函子的第一个参数.some_fun
.x.bar<int>(y)
where y
is the first parameter passed into the resulting functor.some_fun
.但是 x.bar
返回 void,而不是任何函数类型.这就是无法编译的原因.
But x.bar<int>(y)
returns void, not any function type. That's why this doesn't compile.
正如 K-ballo 指出的,使用 boost::bind
,您可以使用 boost::protect
解决这个问题.正如 Kerrek SB 和 ildjarn 指出的那样,解决此问题的一种方法是:不要将 auto
用于 f
.您不希望 f
具有绑定表达式的类型.如果 f
具有其他类型,则 std::bind
不会尝试应用函数组合规则.例如,你可以给 f
类型 std::function
:
As K-ballo points out, with boost::bind
, you can fix this problem with boost::protect
. As Kerrek SB and ildjarn point out, one way around this issue is: don't use auto
for f
. You don't want f
to have the type of a bind expression. If f
has some other type, then std::bind
won't attempt to apply the function composition rules. You might, for instance, give f
the type 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);
由于 f
字面上没有绑定表达式的类型,std::is_bind_expression<>::value
将在 f<上为假/code> 的类型,因此第二行中的
std::bind
表达式只会逐字传递值,而不是尝试应用函数组合规则.
Since f
doesn't literally have the type of a bind expression, std::is_bind_expression<>::value
will be false on f
's type, and so the std::bind
expression in the second line will just pass the value on verbatim, rather than attempting to apply the function composition rules.
这篇关于std::bind 绑定函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!