Контекст:
Я получил следующую иерархию структур:
Event -> MouseEvent -> MouseButtonEvent
-> MouseWheelEvent
-> ...
-> KeyboardEvent -> KeyEvent
-> InputEvent
-> ...
-> ...
Потенциально может быть много разных типов событий. Также есть компоненты heirarchy. Базовый класс Component
:
Component.h:
как я хочу, чтобы он был
class Component
{
...
/* These could be overriden in derived to handle this events. */
virtual void handleEvent(const MouseButtonEvent&);
virtual void handleEvent(const MouseWheelEvent&);
virtual void handleEvent(const KeyEvent&);
virtual void handleEvent(const InputEvent&);
...
...
template<typename GMouseEvent>
void handleMouseEvent(const GMouseEvent& e)
{
if (!children.empty())
{
// Pay attention: I need to cast to real Event type to be able to use event properties here.
const auto& eMouse = static_cast<const MouseEvent&>(e);
auto eCopy = eMouse;
for (auto child : children)
{
// point is a property of MouseEvent
eCopy.point = child->transformPointToLocal(eMouse.point);
if (child->predicateOnMouseEventPropery(eMouse.point))
return child->handleEvent(static_cast<GMouseEvent&>(eCopy)); // Need to save GMouseEvent type to call proper virtual handler
}
}
}
template<typename GNonMouseEvent>
void handleNonMouseEvent(const GNonMouseEvent& e)
{
for (auto child : children)
child->handleEvent(e); // Also need to preserve original call type to call virtual method
}
...
std::vector<Component*> children;
}
...
void Component::handleEvent(const MouseButtonEvent& e)
{
handleMouseEvent<MouseButtonEvent>(e);
}
void Component::handleEvent(const MouseWheelEvent& e)
{
handleMouseEvent<MouseWheelEvent>(e);
}
void Component::handleEvent(const KeyEvent& e)
{
handleNonMouseEvent<KeyEvent>(e);
}
void Component::handleEvent(const InputEvent& e)
{
handleNonMouseEvent<InputEvent>(e);
}
Component.h:
как это на самом деле
class Component
{
...
/* These could be overriden in derived to handle this events. */
virtual void handleEvent(const MouseButtonEvent&);
virtual void handleEvent(const MouseWheelEvent&);
virtual void handleEvent(const KeyEvent&);
virtual void handleEvent(const InputEvent&);
...
std::vector<Component*> children;
}
...
void Component::handleEvent(const MouseButtonEvent& e)
{
if (!children.empty())
{
auto eCopy = e;
for (auto child : children)
{
// point is a property of MouseEvent that is the base of MouseButtonEvent
eCopy.point = child->transformPointToLocal(e.point);
if (child->predicateOnMouseEventPropery(e.point))
return child->handleEvent(eCopy);
}
}
}
void Component::handleEvent(const MouseWheelEvent& e)
{
if (!children.empty())
{
auto eCopy = e;
for (auto child : children)
{
// point is a property of MouseEvent that is the base of MouseWheelEvent
eCopy.point = child->transformPointToLocal(e.point);
if (child->predicateOnMouseEventPropery(e.point))
return child->handleEvent(eCopy);
}
}
}
void Component::handleEvent(const KeyEvent& e)
{
for (auto child : children)
child->handleEvent(e);
}
void Component::handleEvent(const InputEvent& e)
{
for (auto child : children)
child->handleEvent(e);
}
MyComponent.h:
class MyComponent : public Component
{
virtual void handleEvent(const MouseButtonEvent& e);
virtual void handleEvent(const KeyEvent& e);
...
}
void MyComponent::handleEvent(const MouseButtonEvent& e)
{
// Calling for virtual void Component::handleEvent(const MouseButtonEvent&)
Component::handleEvent(e);
... // doing other stuff
}
void MyComponent::handleEvent(const KeyEvent& e)
{
// Calling for virtual void Component::handleEvent(const KeyEvent&)
Component::handleEvent(e);
... // doing stuff
}
Somewhere else:
...
Component* c = myComponentPointer;
MouseButtonEvent e = {};
e.point = {10, 20};
e.foo = "bar";
// Just call virtual overloaded function here to be as simple from the side as possible
// Calling here virtual void MyComponent::handleEvent(const MouseButtonEvent&);
c->handleEvent(e);
...
Вопрос
Я хочу сохранить этот шаблон вызова, когда я просто вызовите виртуальные функции, которые реализованы для конечных узлов иерархии событий. Но я хочу поместить некоторый код в Component::handleEvent
для каждой из этих виртуальных функций, которым просто не нужны ни конечные узлы, ни событие root. Как мне переписать template<typename GMouseEvent> void handleMouseEvent(const GMouseEvent& e)
и template<typename GNonMouseEvent> void handleNonMouseEvent(const GMouseNonEvent& e)
?