【问题标题】:bind two function objects绑定两个函数对象
【发布时间】:2011-11-01 10:31:53
【问题描述】:

使用clang++ -std=c++0x -stdlib=libc++ main.cpp 构建

#include <string>
#include <functional>

using std::bind;
using std::string;
using std::function;

class Service
{
public:
    void listen( const function< void ( const string&, const string&, const string&, const string& ) > const& login )
    {

    }
};

class Threadpool
{
public:
    void schedule( const function< void ( void ) > const& task )
    {

    }
};

class Server
{
    public:
    Server( )
    {
        Threadpool* threadpool = new Threadpool( );

        Service* service = new Service( );

        threadpool->schedule( bind( &Service::listen, service, mem_fn( &Server::subscribe ) ) );
    }

    void subscribe( const string& username, const string& password, const string& hostname, const string& data )
    {

    }
};

int main ( int argc, char** argv )
{
    Server server( );   
}

错误:

In file included from main.cpp:3:
/usr/include/c++/v1/functional:892:22: error: no matching function for call to '__invoke'
              return __invoke(__f_, _STD::forward<_ArgTypes>(__args)...);
                     ^~~~~~~~
/usr/include/c++/v1/__functional_base:437:12: note: in instantiation of function template specialization 'std::__1::__mem_fn<void
      (Server::*)(const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &)>::operator()<const std::__1::basic_string<char> &, const std::__1::basic_string<char>
      &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &>' requested here
    return _STD::forward<_F>(__f)(_STD::forward<_T>(__t)...);
           ^
/usr/include/c++/v1/__config:153:14: note: instantiated from:
#define _STD std::_LIBCPP_NAMESPACE
             ^
/usr/include/c++/v1/functional:1054:12: note: in instantiation of function template specialization
      'std::__1::__invoke<std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &>' requested here
    return __invoke(__f_.first(), _STD::forward<_ArgTypes>(__arg)...);
           ^
/usr/include/c++/v1/functional:1256:26: note: in instantiation of member function
      'std::__1::__function::__func<std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)>,
      std::__1::allocator<std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> >, void (const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &)>::operator()' requested here
            ::new (__f_) _FF(_STD::move(__f));
                         ^
/usr/include/c++/v1/__functional_base:349:47: note: in instantiation of function template specialization 'std::__1::function<void
      (const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &)>::function<std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> >' requested
      here
    return ((*_STD::forward<_T1>(__t1)).*__f)(_STD::forward<_Arg>(__arg)...);
                                              ^
/usr/include/c++/v1/__config:153:14: note: instantiated from:
#define _STD std::_LIBCPP_NAMESPACE
             ^
/usr/include/c++/v1/functional:1652:12: note: in instantiation of function template specialization 'std::__1::__invoke<void,
      Service, Service *&, const std::__1::function<void (const std::__1::basic_string<char> &, const std::__1::basic_string<char>
      &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> &, std::__1::__mem_fn<void (Server::*)(const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &)> &>' requested here
    return __invoke(__f, __mu(get<_Indx>(__bound_args), __args)...);
           ^
/usr/include/c++/v1/functional:1681:20: note: in instantiation of function template specialization 'std::__1::__apply_functor<void
      (Service::*)(const std::__1::function<void (const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> &), std::__1::tuple<Service *, std::__1::__mem_fn<void
      (Server::*)(const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &)> >, 0, 1, std::__1::tuple<> >' requested here
            return __apply_functor(__f_, __bound_args_, __indices(),
                   ^
/usr/include/c++/v1/__functional_base:437:12: note: in instantiation of function template specialization 'std::__1::__bind<void
      (Service::*)(const std::__1::function<void (const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> &), Service *, std::__1::__mem_fn<void
      (Server::*)(const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &)> >::operator()<>' requested here
    return _STD::forward<_F>(__f)(_STD::forward<_T>(__t)...);
           ^
/usr/include/c++/v1/__config:153:14: note: instantiated from:
#define _STD std::_LIBCPP_NAMESPACE
             ^
/usr/include/c++/v1/functional:1054:12: note: in instantiation of function template specialization
      'std::__1::__invoke<std::__1::__bind<void (Service::*)(const std::__1::function<void (const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> &),
      Service *, std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &, const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> > &, >' requested here
    return __invoke(__f_.first(), _STD::forward<_ArgTypes>(__arg)...);
           ^
/usr/include/c++/v1/functional:1256:26: note: in instantiation of member function
      'std::__1::__function::__func<std::__1::__bind<void (Service::*)(const std::__1::function<void (const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &)> &), Service *, std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> >,
      std::__1::allocator<std::__1::__bind<void (Service::*)(const std::__1::function<void (const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> &),
      Service *, std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &, const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> > >, void ()>::operator()' requested here
            ::new (__f_) _FF(_STD::move(__f));
                         ^
main.cpp:36:31: note: in instantiation of function template specialization 'std::__1::function<void
      ()>::function<std::__1::__bind<void (Service::*)(const std::__1::function<void (const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> &), Service *,
      std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &)> > >' requested here
        threadpool->schedule( bind( &Service::listen, service, mem_fn( &Server::subscribe ) ) );
                              ^
/usr/include/c++/v1/__functional_base:293:1: note: candidate template ignored: substitution failure [with _R = void, _T = Server,
      _T1 = const std::__1::basic_string<char> &, _Param = <const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &>, _Arg = <const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &>]
__invoke(_R (_T::*__f)(_Param...), _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:306:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const, _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:319:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) volatile, _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:332:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const volatile, _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:347:1: note: candidate template ignored: substitution failure [with _R = void, _T = Server,
      _T1 = const std::__1::basic_string<char> &, _Param = <const std::__1::basic_string<char> &, const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &>, _Arg = <const
      std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char> &>]
__invoke(_R (_T::*__f)(_Param...), _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:360:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const, _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:373:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) volatile, _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:386:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const volatile, _T1&& __t1, _Arg&& ...__arg)
^
/usr/include/c++/v1/__functional_base:400:1: note: candidate function template not viable: requires 2 arguments, but 5 were
      provided
__invoke(_R _T::* __f, _T1&& __t1)
^
/usr/include/c++/v1/__functional_base:425:1: note: candidate function template not viable: requires 2 arguments, but 5 were
      provided
__invoke(_R _T::* __f, _T1&& __t1)
^
/usr/include/c++/v1/__functional_base:435:1: note: candidate template ignored: substitution failure [with _F = void
      (Server::*&)(const std::__1::basic_string<char> &, const std::__1::basic_string<char> &, const std::__1::basic_string<char>
      &, const std::__1::basic_string<char> &), _T = <const std::__1::basic_string<char> &, const std::__1::basic_string<char> &,
      const std::__1::basic_string<char> &, const std::__1::basic_string<char> &>]
__invoke(_F&& __f, _T&& ...__t)
^
1 error generated.

【问题讨论】:

  • Clang 有很棒的错误信息,请发布,它可以帮助大家理解问题...
  • 很遗憾,我目前无法访问错误消息。我将在今晚晚些时候提交。感谢您的宝贵时间。
  • 请提供从产生第一条编译器错误消息的代码复制/粘贴的完整示例。在为您提供一些包含后,我得到:Thread 未定义。
  • Service::up 错过了模板中的结束 &gt;
  • 完整示例现已发布,干杯。

标签: c++ c++11 clang std-function stdbind


【解决方案1】:

家庭作业?如果是这样,我会得到一些荣誉。 :-)

我看到你刚刚在我研究你的问题时自己纠正了你的第一个错误,所以我会跳过那个。

下一步:

&amp;Service::listen 期待 function&lt;void(string, string, string, string)&gt;。您需要将其中一项显式传递给bind

bind( &Service::listen, service, function< void ( const string&, const string&,
                                                  const string&, const string& ) >
                                                        (something goes here) )

我会在第二部分再次使用bind,但是您需要说明这个辅助仿函数除了Server* 之外还需要4 个参数。这些参数是 4 个字符串,尚不可用。您可以为这些字符串传入“占位符”。这是由以下人员完成的:

    using namespace std::placeholders;
    threadpool->schedule(
         bind( &Service::listen, service,
               function< void ( const string&, const string&,
                                const string&, const string& ) >(
                   bind( &Server::subscribe, this, _1, _2, _3, _4 ) ) ) );

将所有内容放在一起,并放入一些打印语句以供确认:

#include <string>
#include <functional>
#include <iostream>

using std::bind;
using std::string;
using std::function;

class Service
{
public:
    void listen( function< void ( const string&,
                                  const string&,
                                  const string&,
                                  const string& ) > const& login )
    {
        std::cout << "in listen\n";
        login("w", "x", "y", "z");
    }
};

class Threadpool
{
public:
    void schedule( const function< void ( void ) > const& task )
    {
        std::cout << "in schedule\n";
        task();
    }
};

class Server
{
    public:
    Server()
    {
        Threadpool* threadpool = new Threadpool( );
        Service* service = new Service( );

        using namespace std::placeholders;
        threadpool->schedule(
             bind( &Service::listen, service,
                   function< void ( const string&, const string&,
                                    const string&, const string& ) >(
                       bind( &Server::subscribe, this, _1, _2, _3, _4 ) ) ) );
    }

    void subscribe( const string& username, const string& password,
                    const string& hostname, const string& data )
    {
        std::cout << "in subscribe\n";
        std::cout << username << '\n';
        std::cout << password << '\n';
        std::cout << hostname << '\n';
        std::cout << data << '\n';
    }
};

int main ()
{
    Server server;   
}

我明白了:

in schedule
in listen
in subscribe
w
x
y
z

顺便说一句,这会泄漏内存。更正那是留给读者的练习。 :-)

【讨论】:

  • 让霍华德大吃一惊:p 我刚刚在两秒钟前自己整理过。
【解决方案2】:

为了完整起见,我的解决方案如下。

#include <string>
#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;
using std::string;
using std::function;
using std::placeholders::_1;
using std::placeholders::_2;
using std::placeholders::_3;
using std::placeholders::_4;
using std::placeholders::_5;

class Service
{
public:
    void listen( const function< void ( const string&, const string&, const string&, const string& ) > const& login )
    {
        login( "ben", "crowhurst", "localhost", "some data" );
    }
};

class Threadpool
{
public:
    Threadpool( ) { }

    void schedule( const function< void (  ) > const& task )
    {
        cout << "in schedule" << endl;

        task( );
    }
};

class Server
{
    public:
    Server( )
    {
        Threadpool* threadpool = new Threadpool( );

        Service* service = new Service( );

        function<void (const string&, const string&, const string&, const string&)> f1 = 
        bind( &Server::subscribe, this, _1, _2, _3, _4 );

        auto f2 = bind( &Service::listen, service, f1 );

        threadpool->schedule( f2 );
    }

    void subscribe( const string& username, const string& password, const string& hostname, const string& data )
    {
        cout << "username: " << username << endl;
        cout << "password: " << password << endl;
        cout << "hostname: " << hostname << endl;
        cout << "    data: " << data << endl;
    }
};

int main ( int argc, char** argv )
{
    cout << "in main" << endl;

    Server* server = new Server( );  
}

【讨论】:

    【解决方案3】:

    首先,typedef 是你的朋友:

    typedef std::function<void(void)> RequestFunc;
    typedef std::function<void(const std::string&, const std::string&)> DispatchFunc;
    

    我们现在可以按如下方式提交您的声明。我已将参数更改为 deliver 以采用 dispatchFunc(因为原来的参数是不带参数的 void)。由于可访问性问题,我还在类声明之后添加了;,并使您尝试与public 绑定的函数:

    class A {
           std::string name;
           std::string location;
    public:
           void deliver( const DispatchFunc& request )
           {
              request( name, location );
           }
        };
    
     class B {
     public:
           void dispatch( const DispatchFunc& request )
           {
           };
        };
    

    其次,我怀疑您的deliver() 函数实际上需要DispatchFunc typedef。在不知道您的 sn-p 用途的​​情况下,很难说出您想要绑定的类型。

    现在已经排序,进入声明。由于与 Windows 套接字库的命名冲突,使用 bind(至少在 Windows 中)存在问题。这可能是编译器的问题,也可能不是问题,但在 boost 命名空间前加前缀总是一个好主意:

     B b;
     auto func1 = boost::bind( &B::dispatch, b );
    
     A a;
     auto func2 = boost::bind( &A::deliver, a, func1);
    

    这些修改为我成功编译。至于其余的以及你打算做什么,祝你好运。

    【讨论】:

    • 您好,感谢您的宝贵时间。 Deliver 方法需要 std::function 因为传入的函数对象的类型会改变。
    • @BenCrowhurst,但是你不能突然把它当作一个接受两个参数的函数(那个函数就是这样)。
    • @Ben,你怎么能用参数调用void(void) 函数?
    • auto f = bind(&A::deliver, a, func1);然后 f( );
    • @Ben,将func1 作为参数绑定到实例adeliver 函数。但是func1 是指向B 的成员函数dispatch 的指针,它需要一个(或两个)参数,但您没有将参数绑定到B::dispatch...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2014-07-21
    相关资源
    最近更新 更多