Search code examples
c++c++11clangstd-functionstdbind

bind two function objects


Building with 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( );   
}

ERROR:

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.

Solution

  • Homework? If so, I get some credit. :-)

    I see you just corrected your first error yourself as I was studying your problem, so I'll skip that one.

    Next:

    &Service::listen is expecting a function<void(string, string, string, string)>. You need to pass one of these explicitly into the bind.

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

    I would use bind for this second part again, but you need to express that this secondary functor is something that will take 4 parameters in addition to the Server*. These parameters are the 4 strings, which aren't yet available. You can pass in "placeholders" for these strings. This is done by:

        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 ) ) ) );
    

    Putting it all together, and putting in some print statements for confirmation:

    #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;   
    }
    

    I get:

    in schedule
    in listen
    in subscribe
    w
    x
    y
    z
    

    By the way, this leaks memory. Correcting that is left as an exercise for the reader. :-)