21

我无法检测为什么这不编译。我有一些std::function基于某个参数返回 a 的 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 错误输出,我无法弄清楚出了什么问题。这是 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::bindstd::function

4

2 回答 2

21

std::bind表达式,像它们的boost::bind前辈一样,支持一种组合操作。你的表达w大致相当于

auto w=std::bind(some_fun,  std::bind(&foo::bar<int>, x, std::placeholders::_1) );

以这种方式嵌套绑定被解释为

  1. 计算x.bar<int>(y)where的值y是传递给结果仿函数的第一个参数。
  2. 将该结果传递给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);

由于f实际上没有绑定表达式的类型,因此在' 类型std::is_bind_expression<>::value上将为 false ,因此第二行中的表达式将逐字传递值,而不是尝试应用函数组合规则。fstd::bind

于 2012-05-28T00:54:26.140 回答
-3

some_fun想要类型的参数const std::function<void(int)> &

std::bind 返回“未指定类型 T 的函数对象”(查看提供的链接,“返回值”部分),您试图将其作为 some_fun 参数传递。

似乎这会导致问题,因为不需要这种参数类型。

看看:http ://en.cppreference.com/w/cpp/utility/functional/bind

于 2012-05-27T21:59:28.110 回答