I have many interfaces for different listeners, the all look like this:
class ListenerA
{
public:
virtual void
onEventA(const EventA&) = 0;
};
class ListenerB
{
public:
virtual void
onEventB(const EventB&) = 0;
};
When testing, I always end up just collecting those events in a std::vector
for analyzing them afterwards in a specific test suite. Those event collectors all look the same like this one for example:
class EventACollector : public ListenerA
{
public:
const auto&
events() const
{
return m_events;
}
private:
void
onEventA(const EventA& event) override
{
m_events.emplace_back(event);
}
std::vector<EventA> m_events;
};
Is there a way to template an EventTCollector, so that I do not have to write it every time? Given that the virtual function name does change for every listeners?
CodePudding user response:
C does not have introspection, so you cannot find the virtual
function in ListenerA
. The other parts can go in a templated base class, but the override you'll need to define manually.
Modern C would use a std::function<void(EventA)>
instead of a named interface, but that won't help you as a user of that old interface.
CodePudding user response:
Supposed you make your interface a template (this isnt necessary, but will make the collector more straight forward):
template <typename Event>
class ListenerA {
public:
using event_type = Event;
virtual void onEventA(const event_type&) = 0;
};
Then the collector can be:
template <typename Listener>
class EventACollector : public Listener {
public:
const auto& events() const { return m_events; }
private:
void onEventA(const EventA& event) override {
m_events.emplace_back(event);
}
std::vector<typename Listener::event_type> m_events;
};