首页 文章

std ::绑定绑定函数

提问于
浏览
21

我'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::bindstd::function .

2 回答

  • -3

    std::bind表达式,就像它们的 boost::bind 前辈一样,支持一种合成操作 . 您对 w 的表达式大致相当于

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

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

    • 计算 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)>

    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<>::valuef 的类型上将为false,因此第二行中的 std::bind 表达式将只传递逐字的值,而不是尝试应用函数组合规则 .

  • 21

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

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

    这似乎会导致问题,因为这种参数类型不是预期的 .

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

相关问题