Search code examples
c++templatesinheritanceshared-ptr

C++ Templated Subject Observer Inheritance/Cast Conflict


I am using the example http://www.codeproject.com/Articles/3267/Implementing-a-Subject-Observer-pattern-with-templ to implement a templated subject/observer pattern. However, I am getting annoying compile errors looking like inheritance isn't working, or an odd cast. Any help would be great. At the bottom of the post is the line causing the issue.

The error

FooManager.h: In member function
    'ReturnEnum FooManager::AddBar(BarPtr)':

Foo.h:150: error: no matching function for call to
    'Bar::attach(FooManagerPtr)'

Subject.h:23: note: candidates are: 
    void Subject<T>::attach(Observer<T>) [with T = boost::shared_ptr<Bar>]

The Code

types.h

class Bar;
typedef boost::shared_ptr<Bar> BarPtr;

class FooManager;
typedef boost::shared_ptr<FooManager> FooManagerPtr;

Observer.h

#include "types.h"
template <class T>
class Observer
{
    public:
        Observer(){}
        virtual ~Observer() {}
        virtual void update(T subject) = 0;
};

Subject.h

#include "types.h"
template <class T>
class Subject
{
    private:
        vector< Observer<T> > m_observers;

    public:
        Subject() {}
        virtual ~Subject() {}
        void attach(Observer<T> observer)
        {
            m_observers.push_back(observer);
        }

        void notify()
        {
            for(vector< Observer<T> >::iterator it = m_observers.begin(); it != m_observers.end(); ++it)
            {
                (*it)->update(static_cast<T>(this));
            }
        }
};

Bar.h

#include "types.h"
class Bar             : public Subject<BarPtr>
{
};

FooManager.h

#include "types.h"
class FooManager                : public Observer<BarPtr>
{
    public:
        ReturnEnum AddBar(BarPtr pBar)
        {
            pBar->attach( FooManagerPtr(this, boost_null_deleter()) );
        }
};

Solution

  • Depending on what you want to achieve, you could try to change (warning, untested code!):

        void attach(Observer<T> observer)
        {
            m_observers.push_back(observer);
        }
    

    to

        void attach(boost::shared_ptr<Observer<T>> observer)
        {
            m_observers.push_back(observer);
        }
    

    and

    vector< Observer<T> > m_observers;
    

    to

    vector< boost::shared_ptr<Observer<T> > > m_observers;