обратный вызов std :: function с аргументами в шаблоне наблюдателя (заполнитель на тему регистра)

0

Я работаю над классом менеджера ввода, основанным на шаблоне наблюдателя, используя std :: function и std :: bind.

Класс входного менеджера выводится из класса "Observable", который включает в себя метод "Register (...)":

  std::map<Event, std::vector<std::function<void()>>> m_observers;

  template <class Observer, class... Args>
  void Register(Event&& event, Observer&& observer, Args&&... args)
  {
      m_observers[std::move(event)].push_back(std::bind(std::forward<Observer>(observer), std::forward<Args>(args)...));
  }

Таким образом, вы можете регистрировать темы в менеджере ввода. Менеджер ввода, чем отправляет текущий вход (данный из ОС) всем его слушателям (темам). Для этого будет вызван зарегистрированный обратный вызов субъекта. Этот обратный вызов должен иметь произвольную подпись.

В тематическом классе я вызываю регистр при инициализации следующим образом:

GameApp::InputManager.Register(
    InputType::Keyboard,
    &IntroGameState::OnInput,
    this,
    //sf::Event()
    std::placeholders::_1
  );

Произошла следующая ошибка компилятора:

c:\program files (x86)\microsoft visual studio 12.0\vc\include\function (900): ошибка C2027: использование неопределенного типа 'std :: tuple_element <0, _Ftuple>'

Если передать действительный аргумент методу register (как args...), например, "sf :: Event()", все работает. Но в данный момент я только хотел бы зарегистрировать тему и сказать, какой вызов следует вызывать в случае, если менеджер ввода имеет некоторый ввод для объекта. Я хочу дать аргумент от менеджера ввода к теме. И не вице-верка. При регистрации субъекта субъекту я не знаю аргументов. Аргументы должны быть предоставлены от менеджера к предмету (через обратный вызов). Поэтому я думал, что местозаполнитель в регистровом коде (по теме) будет в порядке. Но это приводит к ошибке компилятора, как упоминалось выше.

Любые идеи, как я могу решить проблему?

Теги:
function
std
bind
observer-pattern

1 ответ

1
Лучший ответ

Вы пытаетесь заполнить слот формы

std::function<void()>

с результатом вызова std::bind с std::placeholders::_1 качестве одного из аргументов. Связывание предоставляет operator() который принимает один аргумент, std::function ожидает, что сможет вызвать его с помощью none. Вот почему это не компилируется.

Если я понимаю, что вы пытаетесь правильно, ваша карта должна быть типа

                                            // v---- here ----v
std::map<Event, std::vector<std::function<void(SomeClass const &)>>> m_observers;

Где SomeClass инкапсулирует данные, необходимые для возврата к обратным SomeClass.

  • 0
    Спасибо за вашу помощь. Теперь это работает. Я изменил на m_observers: std :: map <Event, std :: vector <std :: function <void (const void *) >>> m_observers; и мой обработчик обратного вызова выглядит следующим образом: void IntroGameState :: OnInput (const void * data) {const sf :: Event * eventData = static_cast <const sf :: Event *> (data); // далее код} Но я думаю, что это грязно :)
  • 0
    const void * .... это определенно грязно! :-(
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню