I am utilizing an observer design pattern for this simple use case whereupon a change in a Subject
concrete class, the template value _x
is passed to the observers via notify()
however that will require Subject
to be a template class which I don't want.
Instead of making Subject
a template class, I made notify
a template function and made Observer
a template to allow the passing of a template value
in update()
but that will cause problems inside Subject
which doesn't need to be a template class.
Any ideas on getting around this problem without making Subject
template?
class Subject;
template<typename T>
class Observer
{
public:
virtual void update(T value, Subject *) = 0;
};
class Subject
{
std::vector<Observer<T>*> _obs;
public:
void attach(Observer<T>* obs)
{
_obs.push_back(obs);
}
template<typename T>
void notify(T value)
{
for (auto& o: _obs)
{
o->update(value, this);
}
}
};
template<typename T>
class B : public Observer<T>
{
public:
void update(T value, Subject* sub)
{
std::cout << "Value set = " << value << std::endl;
}
};
template<typename T>
class A : public Subject
{
T _x;
public:
void set(T value)
{
_x = value;
notify(_x); // want to pass T without making Subject template
}
};
int main()
{
A<int> a1;
B <int> b1;
a1.attach(&b1);
a1.set(10);
}
CodePudding user response:
If you really promise that for notify<T>
, there are only Observer<T>
, then you could use a dynamic_cast safely:
class Subject;
class ObsBase{
virtual ~ObsBase()=default;
};
template<typename T>
class Observer:public ObsBase
{
public:
virtual void update(T value, Subject *) = 0;
};
class Subject
{
//If this is the owner, use std::unique_ptr<ObsBase>
std::vector<ObsBase*> _obs;
public:
void attach(ObsBase* obs)
{
_obs.push_back(obs);
}
template<typename T>
void notify(T value)
{
for (ObsBase* o: _obs)
{
auto* d = dynamic_cast<Observer<T>*>(o);
if(d!=nullptr)
d->update(value, this);
}
}
};