Search code examples
c++templatesstlobserver-pattern

implementing Observer pattern in C++


I am writing a very simple implementation of Observer pattern in C++. Because I want my Publisher to notify its subscribers with events that are different (e.g. not just a string, but a specific class), I have decided to use templates. My code is compiling fine, except that part that I don't know where to store all these Observers. If I use and std::list or std::vector, they will not allow to store specialized data, because their elements have to be the same. So my question is, how do I store all those observers in my Publisher class. Here is my code:

Observer.hpp
#ifndef H_OBSERVER
#define H_OBSERVER    

#include <memory>

class Publisher;

template <class T>
class Observer
{
    protected:
    virtual void Notify(std::shared_ptr<Publisher> source, T info) = 0;
};

#endif

Publisher.hpp
#ifndef H_PUBLISHER
#define H_PUBLISHER

#include "Observer.hpp"
#include <list>
#include <string>
#include <memory>

class Publisher
{

public:
    template<class T>
    void NotifyObservers();

    template <class T>
    void AddObserver(std::shared_ptr<Observer<T>> &obs);

    template <class T>
    void RemoveObserver(std::shared_ptr<Observer<T>> &obs);

protected:
    //std::list<std::shared_ptr<Observer> m_observers;
};

#endif

Solution

  • The initial solution I posted was not correct. It's because I am new to templates and did not know how to effectively utilize them. The solution I am posting now is a working one:

    //IObserver.hpp
    #pragma once
    #include <memory>
    
    template <class T>
    class IObserver
    {
    public:
        virtual ~IObserver() {};
        virtual void Notify(T data) = 0;
    protected:
    };
    
    
    
    //Observable.hpp
    #pragma once
    
    #include "IObserver.hpp"
    #include <list>
    #include <string>
    #include <memory>
    
    template<class T>
    class Observable
    {
    public:
        void NotifyObservers(T data)
        {
            for (auto o : m_observers)
            {
                o.Notify(data);
            }
        }
    
        void AddObserver(std::shared_ptr<IObserver<T>> &obs)
        {
            m_observers.push_back(obs);
        }
    
        void RemoveObserver(std::shared_ptr<IObserver<T>> &obs)
        {
            m_observers.remove(obs);
        }
    
    private:
        std::list<std::shared_ptr<IObserver<T>>> m_observers;
    };