I wanted to implement an observer pattern for an event system, but the compiler gives me a bunch of errors and I’m currently not able to fix them. I have two templated class in two different headers, a listener and a event dispatcher and both needs to store pointers to the other class.
In Dispatcher.h
//Dispatcher.h
#pragma once
#include "Listener.h"
template <typename T>
class Dispatcher {
private:
std::vector<Listener<T>*> m_listeners;
public:
Dispatcher() {}
~Dispatcher() {
for (Listener<T>* l : m_listeners) {
delete l;
}
}
void Attach(Listener<T>* listener) {
m_listeners.push_back(listener);
}
void Detach(Listener<T>* listener) {
std::vector<Listener<T>*>::iterator it = std::find(m_listeners.begin(), m_listeners.end(), listener);
if (it != m_listeners.end()) {
m_listeners.erase(it);
}
}
void Notify(T& event) {
for (Listener<T>* l : m_listeners) {
l->OnEvent(event);
}
}
};
In Listener.h
//Listener.h
#pragma once
#include "Dispatcher.h"
template <typename T>
class Listener {
private:
Dispatcher<T>* m_dispatcher;
protected:
Listener(Dispatcher<T>* dispatcher) : m_dispatcher(dispatcher) {
m_dispatcher->Attach(this);
}
public:
virtual ~Listener() {
m_dispatcher->Detach(this);
}
virtual void OnEvent(T& event) = 0;
};
The compiler seems to complain about not being able to find declaration for the listener. What’s wrong with this? Could someone explain? Thanks.
P.S. Obviously there’s a cpp file which includes both headers.
>Solution :
You can solve this problem of circular dependency by removing the #include "Listener.h" from Dispatcher.h and instead adding a forward declaration for class template Listener<> as shown below:
Dispatcher.h
#pragma once
#include <vector>
//no need to include Listener.h
//forward declaration
template<typename T> class Listener;
template <typename T>
class Dispatcher {
private:
std::vector<Listener<T>*> m_listeners;
public:
Dispatcher() {}
~Dispatcher() {
for (Listener<T>* l : m_listeners) {
delete l;
}
}
void Attach(Listener<T>* listener) {
m_listeners.push_back(listener);
}
void Detach(Listener<T>* listener) {
std::vector<Listener<T>*>::iterator it = std::find(m_listeners.begin(), m_listeners.end(), listener);
if (it != m_listeners.end()) {
m_listeners.erase(it);
}
}
void Notify(T& event) {
for (Listener<T>* l : m_listeners) {
l->OnEvent(event);
}
}
};