2016-01-13 4 views
1

Когда событие срабатывает (нажатие клавиши, мышь и т. Д.), Мое приложение вызывает функции делегата, зарегистрированные для этого события.Делегат с шаблонами Variadic

Ниже приведена реализация. Я пытаюсь сделать функцию invoke (()) вариационным шаблоном, чтобы я мог передавать ему какие-либо параметры. Но с моей текущей настройкой ниже ее невозможно.

Любые идеи о том, как я могу добиться использования вариативных шаблонов в этом дизайне?

Редактировать Измененный код

template <typename... params> 
class EventDelegate 
{ 
public: 
    typedef std::function<int(params...)> EDelegate; 

    EventDelegate(EDelegate delegate) : delegate(delegate) 
    { 

    } 

    int operator()(params...) const 
    { 
     return delegate(params...); 
    } 

private: 
    EDelegate delegate; 
}; 

// Not valid because template params are not specified. But each EventDelegate can take different params 
std::unordered_multimap<int, EventDelegate> evtRegistry; 

// Example 

class Foo 
{ 
public: 
    int onLeftClick(GUID sender, Point pos); 
    int onKeyDown(char key); 
}; 

// Usage 

... 

evtRegistry[1] = EventDelegate(std::bind(&Foo::onLeftClick, myFoo, std::placeholders::_1, std::placeholders::_2)); 
evtRegistry[2] = EventDelegate(std::bind(&Foo::onKeyDown, myFoo, std::placeholders::_1)); 

Обработка событий:

LRESULT CALLBACK Win32App::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 

    switch (message) 
    { 
     case WM_CREATE: 
     { 
      auto registeredCmps = evtRegistry.equal_range(EVT_INIT); 
      for (auto iter = registeredCmps.first; iter != registeredCmps.second; iter++) 
       iter->second(); 
     } 
     break; 
     case WM_DESTROY: 
     { 
      auto registeredCmps = evtRegistry.equal_range(EVT_EXIT); 
      for (auto iter = registeredCmps.first; iter != registeredCmps.second; iter++) 
       iter->second(someParam, someOtherParam); 
     } 
     break; 
     ... 
+0

Непонятно, как вы хотите называть 'EventDelegate', не зная, какой параметр передать ... – Jarod42

+0

@ Jarod42 woops это опечатка. Я исправлю это сейчас. Это моя предыдущая реализация. –

+0

Непонятно, как вы будете различать события при итерации через элементы в evtRegistry. Как вы можете вызвать функцию, не зная, как создать шаблон? –

ответ

0

Мой первый наклон, и, возможно, самый простой ответ здесь, чтобы создать отдельные структуры данных для каждого типа событий. Например:

std::vector< EventDelegate< GUID, Point > > clickRegistry 
std::vector< EventDelegate<char> > keyDownRegistry 

Использование

clickRegistry.push_back(EventDelegate(std::bind(&Foo::onLeftClick, myFoo, std::placeholders::_1, std::placeholders::_2))); 

Хотя почему создание отдельного делегата здесь, когда вы могли бы использовать std::function непосредственно неясна. (Я мог бы добавить добавление кучи другой полезности в класс делегата в будущем, и, возможно, это ваше намерение).

Что вы пытаетесь достичь с помощью единой структуры данных, содержащей все зарегистрированные события?

+0

« Что вы пытаетесь достичь с помощью единой структуры данных, содержащей все зарегистрированные события? », Чего хочет каждый программист; Простота, элегантность и совершенство, duh –