【发布时间】:2015-07-14 00:51:09
【问题描述】:
我在检测为什么这不编译时遇到了麻烦。我有一些 lambda 函数,它根据一些参数返回 std::function。
我已将我的问题缩小到这个 sn-p(它不使用 lambda,但完美地重现了我的错误):
#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 错误输出之一,我不知道出了什么问题。这是 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。
【问题讨论】:
-
当您将 auto 替换为
std::function<void(int)>for f 时,它似乎可以工作。 -
这可能不是您问题的答案.. 但是您是否考虑过使用 C++11 附带的本机 lambda 函数(这使得 std::bind 变得不必要)?
-
在 Boost 中,我们有
protect来处理这种情况,但它似乎没有达到标准。 -
f不是std::function,而是一些无法命名的绑定表达式类型。您必须将其显式转换为std::function。这是您不能使用auto的情况之一。 -
见this answer,特别是关于防止急切评估的部分(你不能不改变类型,因为
std::is_bind_expression<>)。