3

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.
Dan D.
  • 73,243
  • 15
  • 104
  • 123
Ben Crowhurst
  • 8,204
  • 6
  • 48
  • 78

3 Answers3

3

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. :-)

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
1

Just for completeness my solution was as follows.

#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( );  
}
Ben Crowhurst
  • 8,204
  • 6
  • 48
  • 78
0

Firstly, typedefs are your friend:

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

We can now present your declarations as follows. I have changed the parameter to deliver to take a dispatchFunc (as the original one was a void taking no parameters). I also added ; after the class declarations and made the functions you are attempting to bind with public, because of accessibility issues:

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

Secondly, I suspect that your deliver() function actually requires a DispatchFunc typedef. Without knowing the purpose of your snippet, it is difficult to tell what you want types you want to bind to.

Now that's sorted, on to the declarations. There are issues with using bind (in Windows, at least) due to naming conflicts with the windows socket library. This may or may not be an issue on your compiler, but it's always a good idea to prefix the boost namespace:

 B b;
 auto func1 = boost::bind( &B::dispatch, b );

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

These modifications got a successful compile for me. As for the rest and what you intend to do, good luck.

Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • Hello, thanks for your time. The deliver method requires std::function as the type of function object being passed in will change. – Ben Crowhurst Nov 01 '11 at 11:59
  • @BenCrowhurst, but then you cannot suddenly treat it like a function that takes two parameters (which that function does). – Moo-Juice Nov 01 '11 at 12:02
  • @Ben, how can you call a `void(void)` function with arguments? – Nim Nov 01 '11 at 12:02
  • auto f = bind( &A::deliver, a, func1 ); then f( ); – Ben Crowhurst Nov 01 '11 at 12:05
  • @Ben, that binds `func1` as the argument to the `deliver` function of the instance `a`. However `func1` is a pointer to member function `dispatch` of `B` which requires an argument (or two), you've not bound the argument(s) to `B::dispatch`... – Nim Nov 01 '11 at 12:08
  • sorry bad example. bind( &SomeClass::method, arg1, arg2, arg3 ); This can be passed in a method such as void exe( std::function& task); for example. Then called as such task( ); – Ben Crowhurst Nov 01 '11 at 12:12