Связывание с параметром производной функции

Можно ли связать функции с производными параметрами? И если как? Я хотел бы иметь возможность хранить функциональные точки для различных функций, которые имеют одинаковую сигнатуру, а именно, они берут класс с входными данными и возвращают класс с выходными значениями. Но разные функции требуют и предоставляют разные параметры, поэтому я пытаюсь зарегистрировать функции, которые принимают производные классы сообщений.

Следующий код работает частично. Я могу зарегистрировать функцию MathService::blank и позже вызвать ее. Но я не могу добавить MathService::add.

Ошибка, которую я получаю:

main.cpp:70:93: ошибка: преобразование из 'std::_Bind_helper&)(RequestMessage&, ReplyMessage&), MathService&, const std::_Placeholder‹1>&, const std::_Placeholder‹2>&>::type { aka std::_Bind(MathService*, std::_Placeholder‹1>, std::_Placeholder‹2>)>}' в нескалярный тип 'Service::serviceFunction_t {aka std::function}' запрошенный serviceFunction_t fn = bind( methodPtr, objectPtr, placeholders::_1, placeholders::_2 );

#include <functional>
#include <unordered_map>
#include <iostream>

using namespace std;

// base class for messages passed around
class BaseMessage
{
  public:
    virtual void print()
    {
      cout << "BaseMessage\n";
    }
};

// request message with data passed to the service
class RequestMessage : public BaseMessage
{
  public:
    RequestMessage( int a_, int b_ ) : a( a_ ), b( b_ ) {}
    int a;
    int b;
    void print()
    {
      cout << "RequestMessage a=" << a << " b=" << b << endl;
    }
};

// reply message with return values from the service
class ReplyMessage : public BaseMessage
{
  public:
    ReplyMessage() : sum( 0 ) {}
    int sum;
    void print()
    {
      cout << "ReplyMessage sum=" << sum << endl;
    }
};

// Example service provider
class MathService
{
  public:

    void blank( BaseMessage& request, BaseMessage& reply )
    {
      request.print();
      reply.print();
    }

    void add( RequestMessage& request, ReplyMessage& reply )
    {
      reply.sum = request.a + request.b;
    }
};


// Class manages services, register a new service with addService and call the service by name using call
class Service
{
  public:
    using serviceFunction_t = function<void ( BaseMessage&, BaseMessage& )>;

    template<class Method, class Obj>
    void addService( string name,  Method methodPtr, Obj objectPtr )
    {
      serviceFunction_t fn = bind( methodPtr, objectPtr, placeholders::_1, placeholders::_2 );

      pair< string, serviceFunction_t> entry( name, fn );
      mFunctionMap.insert( entry );
    }


    void call( const string& name, BaseMessage& request, BaseMessage& reply )
    {
      std::unordered_map<string, serviceFunction_t>::const_iterator it;
      it = mFunctionMap.find( name );

      if( it == mFunctionMap.end() ) {
        std::cout << "service not found: " << name << endl;
        return;
      }

      serviceFunction_t fn =  it->second;
      fn( request, reply );
    }

  private:
    unordered_map<string, serviceFunction_t> mFunctionMap;
};


int main()
{
  MathService math;
  Service service;

  // can add a service with BaseMessages
  service.addService( "blank", &MathService::blank, &math );


  //*****************************************************
  // PROBLEM is here !!
  // can not add a service with derived message types, this causes the bind call to fail in Service::addService()

  service.addService( "add", &MathService::add, &math );

  //*****************************************************

  // this works
  BaseMessage req1, rep1;
  service.call( "blank", req1, rep1 );

  // so does this
  RequestMessage req2( 1, 2 );
  ReplyMessage rep2;

  service.call( "blank", req2, rep2 );

  // this service is not registered
  service.call( "add", req2, rep2 );

}


person user3916030    schedule 06.08.2014    source источник
comment
Хм... ты... возможно... попробовал это?   -  person Brian Bi    schedule 07.08.2014
comment
do — зарезервированное ключевое слово   -  person quantdev    schedule 07.08.2014
comment
Также измените std::placeholders_1 на std::placeholders::_1   -  person usta    schedule 07.08.2014
comment
Почему вы публикуете поддельный код и задаете вопрос, на который вполне можете ответить сами?   -  person 0x499602D2    schedule 07.08.2014


Ответы (1)


1) do — это зарезервированное ключевое слово C++, поэтому ваш код в таком виде никогда не скомпилируется.

2) std::placeholders_1 не существует, вы наверняка имели в виду std::placeholders::_1

3) Как только это будет исправлено, да, он скомпилируется.

person quantdev    schedule 06.08.2014
comment
Спасибо, что указали на очевидное. Предыдущий пример был задуман как концепция того, чего я пытаюсь достичь. Возможно, расширенный пример делает его более понятным, любая помощь приветствуется. - person user3916030; 10.08.2014