привязка двух функциональных объектов

#c #c 11 #clang #std-function #stdbind

#c #c 11 #лязг #std-функция #stdbind

Вопрос:

Построение с 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 stringamp;, const stringamp;, const stringamp;, const stringamp; ) > constamp; login )
    {

    }
};

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

    }
};

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

        Service* service = new Service( );

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

    void subscribe( const stringamp; username, const stringamp; password, const stringamp; hostname, const stringamp; 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> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;)>::operator()<const std::__1::basic_string<char> amp;, const std::__1::basic_string<char>
      amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;>' 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> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;>' 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> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)>,
      std::__1::allocator<std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> >, void (const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;)>::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> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;)>::function<std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> >' 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 *amp;, const std::__1::function<void (const std::__1::basic_string<char> amp;, const std::__1::basic_string<char>
      amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> amp;, std::__1::__mem_fn<void (Server::*)(const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;)> amp;>' 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> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> amp;), std::__1::tuple<Service *, std::__1::__mem_fn<void
      (Server::*)(const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;)> >, 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> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> amp;), Service *, std::__1::__mem_fn<void
      (Server::*)(const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;)> >::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> amp;,
      const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> amp;),
      Service *, std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> > amp;, >' 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> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;)> amp;), Service *, std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> >,
      std::__1::allocator<std::__1::__bind<void (Service::*)(const std::__1::function<void (const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> amp;),
      Service *, std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> > >, 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> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> amp;), Service *,
      std::__1::__mem_fn<void (Server::*)(const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;)> > >' requested here
        threadpool->schedule( bind( amp;Service::listen, service, mem_fn( amp;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> amp;, _Param = <const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;>, _Arg = <const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;>]
__invoke(_R (_T::*__f)(_Param...), _T1amp;amp; __t1, _Argamp;amp; ...__arg)
^
/usr/include/c  /v1/__functional_base:306:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const, _T1amp;amp; __t1, _Argamp;amp; ...__arg)
^
/usr/include/c  /v1/__functional_base:319:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) volatile, _T1amp;amp; __t1, _Argamp;amp; ...__arg)
^
/usr/include/c  /v1/__functional_base:332:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const volatile, _T1amp;amp; __t1, _Argamp;amp; ...__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> amp;, _Param = <const std::__1::basic_string<char> amp;, const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;>, _Arg = <const
      std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;>]
__invoke(_R (_T::*__f)(_Param...), _T1amp;amp; __t1, _Argamp;amp; ...__arg)
^
/usr/include/c  /v1/__functional_base:360:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const, _T1amp;amp; __t1, _Argamp;amp; ...__arg)
^
/usr/include/c  /v1/__functional_base:373:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) volatile, _T1amp;amp; __t1, _Argamp;amp; ...__arg)
^
/usr/include/c  /v1/__functional_base:386:1: note: candidate template ignored: failed template argument deduction
__invoke(_R (_T::*__f)(_Param...) const volatile, _T1amp;amp; __t1, _Argamp;amp; ...__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, _T1amp;amp; __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, _T1amp;amp; __t1)
^
/usr/include/c  /v1/__functional_base:435:1: note: candidate template ignored: substitution failure [with _F = void
      (Server::*amp;)(const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;, const std::__1::basic_string<char>
      amp;, const std::__1::basic_string<char> amp;), _T = <const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;,
      const std::__1::basic_string<char> amp;, const std::__1::basic_string<char> amp;>]
__invoke(_Famp;amp; __f, _Tamp;amp; ...__t)
^
1 error generated.
 

Комментарии:

1. В Clang есть потрясающие сообщения об ошибках, пожалуйста, опубликуйте это, это поможет всем понять проблему…

2. к сожалению, в настоящее время у меня нет доступа к сообщению об ошибке. Я отправлю их позже этим вечером. Спасибо за ваше время.

3. Пожалуйста, предоставьте полный пример, который был скопирован / вставлен из кода, который выдает первое сообщение об ошибке компилятора. После предоставления нескольких включений для вас я получаю: Thread не определено.

4. Service::up пропускает закрытие > в шаблоне.

5. Теперь доступен полный пример, приветствия.

Ответ №1:

Домашнее задание? Если это так, я получаю некоторый кредит. 🙂

Я вижу, вы только что исправили свою первую ошибку самостоятельно, когда я изучал вашу проблему, поэтому я пропущу ее.

Далее:

amp;Service::listen ожидает a function<void(string, string, string, string)> . Вам нужно явно передать один из них в bind .

 bind( amp;Service::listen, service, function< void ( const stringamp;, const stringamp;,
                                                  const stringamp;, const stringamp; ) >
                                                        (something goes here) )
 

Я бы снова использовал bind для этой второй части, но вам нужно выразить, что этот вторичный функтор — это то, что будет принимать 4 параметра в дополнение к Server* . Эти параметры представляют собой 4 строки, которые пока недоступны. Вы можете передать «заполнители» для этих строк. Это делается с помощью:

     using namespace std::placeholders;
    threadpool->schedule(
         bind( amp;Service::listen, service,
               function< void ( const stringamp;, const stringamp;,
                                const stringamp;, const stringamp; ) >(
                   bind( amp;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 stringamp;,
                                  const stringamp;,
                                  const stringamp;,
                                  const stringamp; ) > constamp; login )
    {
        std::cout << "in listenn";
        login("w", "x", "y", "z");
    }
};

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

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

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

    void subscribe( const stringamp; username, const stringamp; password,
                    const stringamp; hostname, const stringamp; data )
    {
        std::cout << "in subscriben";
        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
 

Кстати, это приводит к утечке памяти. Исправление этого оставлено в качестве упражнения для читателя. 🙂

Комментарии:

1. черт бы тебя побрал, Говард: 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 stringamp;, const stringamp;, const stringamp;, const stringamp; ) > constamp; login )
    {
        login( "ben", "crowhurst", "localhost", "some data" );
    }
};

class Threadpool
{
public:
    Threadpool( ) { }

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

        task( );
    }
};

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

        Service* service = new Service( );

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

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

        threadpool->schedule( f2 );
    }

    void subscribe( const stringamp; username, const stringamp; password, const stringamp; hostname, const stringamp; 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:

Во-первых, typedefs — ваш друг:

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

Теперь мы можем представить ваши объявления следующим образом. Я изменил параметр на deliver , чтобы использовать dispatchFunc (поскольку исходный был void, не принимающим параметров). Я также добавил ; после объявления классов и создал функции, с которыми вы пытаетесь связать public , из-за проблем с доступом:

 class A {
       std::string name;
       std::string location;
public:
       void deliver( const DispatchFuncamp; request )
       {
          request( name, location );
       }
    };

 class B {
 public:
       void dispatch( const DispatchFuncamp; request )
       {
       };
    };
 

Во-вторых, я подозреваю, что для вашей deliver() функции действительно требуется DispatchFunc typedef . Не зная цели вашего фрагмента, трудно определить, к каким типам вы хотите привязать.

Теперь это отсортировано, перейдем к объявлениям. Существуют проблемы с использованием bind (по крайней мере, в Windows) из-за конфликтов именования с библиотекой сокетов Windows. Это может быть или не быть проблемой для вашего компилятора, но всегда полезно указывать префикс boost пространства имен:

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

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

Эти изменения привели к успешной компиляции для меня. Что касается остального и того, что вы собираетесь делать, удачи.

Комментарии:

1. Здравствуйте, спасибо за ваше время. Метод доставки требует std::function<void (void)>, поскольку тип передаваемого объекта функции изменится.

2. @BenCrowhurst, но тогда вы не можете внезапно рассматривать его как функцию, которая принимает два параметра (что и делает эта функция).

3. @Ben, как ты можешь вызывать void(void) функцию с аргументами?

4. автоматически f = bind( amp;A::deliver, a, func1 ); затем f( );

5. @Ben, который привязывается func1 в качестве аргумента к deliver функции экземпляра a . Однако func1 это указатель на функцию-член dispatch B , для которой требуется аргумент (или два), к которому вы не привязали аргументы B::dispatch