2016-10-15 3 views
0

Я работаю над системой событий, которая позволяет триггерам отправлять события либо одному обработчику, либо всем обработчикам, связанным с данным типом. Первая - базовая функциональность карты, а последняя в основном соответствует счету ... если вы не хотите полиморфного поведения.Реализация карты типов с полиморфным поиском

class Parent {}; 
class Child : public Parent {};  

// ... 

Parent p; Child c; 
Trigger trigger; 
Handler h1(&p), h2(&c); 

trigger.sendToType<Child>(Event()); // sends the event to h2; OK 
trigger.sendToType<Parent>(Event()); // sends the event to h1 only; NO 

Обработчики регистрируются в зависимости от типа указателя, с которым они созданы. «Тип» h1 - Parent, а «тип» h2 - Child. При базовом сопоставлении идентификаторов типов, используемых в диспетчере (только некоторое целочисленное число, сопоставленное с вектором Handler*), невозможно отправить события детям при отправке родителям.

Единственное решение я могу думать несколько недостатков:

  • O (N) поиск для отправки к типу.
  • Имея добавить отражение в кодовую
  • высокое количество ручной настройки

В идеале я хотел бы решение, где над головой сводится к (число детей, + 1 для фактического типа) на поиски отправьте по типу, но это может быть невозможно. Любой совет?

+0

Это всегда меня беспокоит, когда люди, которые не знают, как что-то делать, делают всевозможные предположения о том, как вещи должны быть сделаны в их вопросе. «тривиально» «естественно» «К сожалению». Похоже, вы уже создали свой ум. Вы все это время пытались рассказать нам, что у вас есть, и недостаточно говорить о том, что вы действительно пытаетесь решить. Вы уже углубили себя в решение проблемы, которую никто не знает. Этот пост, как есть, лучше подходит для codereview.stackexchange.com – xaxxon

+0

как насчет использования dynamic_cast? – Evgeniy

+0

@xaxxon жаль, если я натолкнулся на снисхождение или невосприимчивость, это было не мое намерение. Причина, по которой я предоставлял столько информации, состояла в том, что я подумал, что это может прояснить то, что я ищу. Я удалю пух, если это станет вопросом лучше. – budjmt

ответ

1

Самое простое решение - использовать dynamic_cast. Может быть, это не является оптимальным с точки зрения производительности, но они должны быть быстрее, чем карта/хэш

Here is implementation - test online

#include <iostream> 
#include <string> 
#include <vector> 

struct Event 
{ 
    std::string what; 
}; 

class Parent 
{ 
public: 
    virtual void process(const Event& e) 
    { 
     std::cout << e.what << "Parent" << std::endl; 
    } 
}; 
class Child : public Parent 
{ 
public: 
    virtual void process(const Event& e) override 
    { 
     std::cout << e.what << "Child" << std::endl; 
    } 
}; 

template<typename T> 
void handler(Parent* obj, const Event& e) 
{ 
    if (T* tmp = dynamic_cast<T*>(obj)) 
     tmp->process(e); 
} 

template<typename T, typename PARENT> 
std::vector<T*> select_objects(const std::vector<PARENT*>& objects) 
{ 
    std::vector<T*> res; 
    for (auto obj : objects) 
    { 
     if (T* tmp = dynamic_cast<T*>(obj)) 
      res.push_back(tmp); 
    } 
    return res; 
} 

int main() 
{ 
    std::vector<Parent*> objects = {new Parent, new Child}; 

    Event e{"Hello from "}; 
    std::cout << "All objects" << std::endl;  
    for (auto p : objects) 
     handler<Parent>(p, e); 
    std::cout << "Child objects only" << std::endl;  
    for (auto p : objects) 
     handler<Child>(p, e); 

    // here we can build an index to access objects faster 
    std::cout << "Child objects only using select" << std::endl;  
    std::vector<Child*> children = select_objects<Child>(objects); 
    for (auto o : children) 
     o->process(e); 
} 

Выход:

All objects 
Hello from Parent 
Hello from Child 
Child objects only 
Hello from Child 
Child objects only using select 
Hello from Child 

UPDATE: вы можете построить некоторый индекс к быстрее доступ к объектам

+0

Это похоже на довольно хорошее решение! Я думаю, что смогу приспособить это, чтобы оно работало. У него проблема с отправкой O (n), но это может быть или не быть неизбежным. Позвольте мне внести несколько изменений в вопрос. – budjmt

+0

Это разрешает только одну реализацию обработчика для каждого типа. – xaxxon

+0

@budjmt "выпуск O (n) отправить на тип:« Плохая форма для создания новых требований в ответ на ответы. – xaxxon

Смежные вопросы