Title: Implementing the observer pattern using CRTP and 'anonymous types/template'
Tags: c++;templates;c++11;observer-pattern;crtp
Question: I'm developing a library that parses a certain XML file (using RapidXML) and returns an object of mine, containing that file data. That XML file is created by someone else's application. I needed to use the observer pattern because speed is extremely crucial, for example:
Suppose a file has 10.000  tag and its child nodes. In a simple parser, they would be added to a st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0vector in the order they were found. Then, after the file was parsed, we would need to iterate over the 10.000 values AGAIN and do whatever we want with them.
By using the observer pattern, I allow external observers (whichever class that wants to observe and be notified about each fetched node has to inherit from AbstractObserver that comes with my library, and implement his functions) to be a part of the parsing process without the need to iterate X times again over the parsed nodes. HOWEVER... There are multiple kinds of nodes, for example: tileset, layer, imagelayer and so on (being necessary multiple onObserved and notify functions for its corresponding node, according to the Observer/Subject pattern, probably having a lot of 'duplicated' code - NOTE: inheritance is not used. See bellow a 'bad' example). I could simply make the nodes inherit from some sort of BaseNode class, but I dont want to use inheritance here since I dont want to deal with pointers. Instead, I'm using enums to type the nodes and thats where my problem lies.
/* ################## ABSTRACT OBSERVER #################### */
// Implements the observer pattern, using the CRTP pattern
template<class ConcreteObserver&gt;
class AbstractObserver
public:
virtual ~AbstractObserver() { }
template<class Attribute&gt;
inline void onObserved(Attribute attribute) {
// This requires ConcreteObserver to have a method onObservedImpl<Attribute&gt;
static_cast<const ConcreteObserver*&gt;(this)-&gt;onObservedImpl(attribute);
/* ################## ABSTRACT SUBJECT #################### */
class AbstractSubject
public:
virtual ~AbstractSubject() { }
// ???????
inline void attach(AbstractObserver<??????&gt;* observer) {
m_observers.push_back(observer);
// ???????
inline void detatch(AbstractObserver<??????&gt;* observer) {
auto&amp; it = st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0find(m_observers.begin(), m_observers.end(), observer);
// Remove the observer from the list, if it was observing
if (it != m_observers.end())
m_observers.erase(it);
protected:
template<typename Attribute&gt;
void notify(Attribute&amp; attribute) {
for (auto* observer : m_observers)
observer-&gt;onObserved(attribute)
private:
// ???????
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0vector<AbstractObserver<??????&gt;*&gt; m_observers;
/* ################## CONCRETE OBSERVER #################### */
class SomeConcreteObserver : public AbstractObserver<SomeConcreteObserver&gt;
public:
// The CRTP 'virtual' function implementation
template<class Attribute&gt;
void onObservedImpl(Attribute attribute)
// Filter the attribute and use it accordingly
switch (attribute.type)
{
// ....
}
/* ################## CONCRETE SUBJECT #################### */
class Parser : public AbstractSubject
public:
void parse(/* params */)
Foo f;
notify<Foo&gt;(f);
// Later on....
Bar b;
notify<Bar&gt;(b);
As we can see, I'm using the CRTP as well, since I need 'templated virtual functions', which is impossible to achieve otherwise. Since the AbstractObserver needs a type (because of the CRTP), I can't properly use them in the AbstractSubject class (see above). Is it even possible to use annonymous templates just like Java, or something like that? I believe this WOULD do the job.
Here is the implementation of a 'bad' example I thought of, but this is the best I could come up with for this situation:
// Remove the CRTP
class AbstractObserver
public:
virtual ~AbstractObserver() { }
virtual void onNodeA(NodeA n) = 0;
virtual void onNodeB(NodeB n) = 0;
virtual void onNodeC(NodeC n) = 0;
virtual void onNodeD(NodeD n) = 0;
virtual void onNodeE(NodeE n) = 0;
// .....
class AbstractSubject
public:
// ....
protected:
void notifyNodeA(NodeA n) {
for (auto* observer : m_observers)
observer-&gt;onNodeA(n);
void notifyNodeB(NodeB n) {
for (auto* observer : m_observers)
observer-&gt;NodeB(n);
void notifyNodeC(NodeC n) { }
void notifyNodeD(NodeD n) { }
void notifyNodeE(NodeE n) { }
// ....
private:
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0vector<Observer*&gt; m_observers;
The solution has to use C++11 or bellow and no boost.
Comment: I'm afraid this is not a proper usage of generics - it works in java just because java upcasts it all to object and then does typechecks. You can do that in C++ too (void* + dynamic_cast) if you insist...

Comment: @user3159253 Hi. It's complicated, I'll try to explain. There's this xml file. My file class is basically a bunch of vectors of different types (contents are static). There will be external classes that I don't know of that will consume my file object. The file class can have vectors of pointers, yes, and 'delete' them on dtor. If the file would have pointers and they all will be destroyed on dtor, the consumer class would have the pointers invalidated too, unless they keep a reference/pointer to the file in their class, which I don't 'recommend' (that's why no pointers in the file)

Comment: @Alegnem I know. It's just a mere example of how is like it to be working. I found 2 solutions for this, which is inheriting the nodes from a base class and store the pointers in the file class or using multiple onNotified and notifyX functions for each xml node (that sounds really wrong), though I'm asking if there's a decent way for doing this

Comment: may I ask why you mind against 'pointers'?

Here is the accepted answer: Solution #1: Quite wet but simple
#include <vector&gt;
#include <algorithm&gt;
#include <iostream&gt;
template<typename TAttribute&gt;
class Observer
public:
virtual void Observe(TAttribute&amp; attribute) = 0;
virtual ~Observer() = default;
template<typename TAttribute&gt;
class OutputtingObserver : public Observer<TAttribute&gt;
public:
void Observe(TAttribute&amp; attribute)
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0cout << attribute << st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0endl;
~OutputtingObserver() = default;
template<typename TAttribute&gt;
class Subject
private:
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0vector<Observer<TAttribute&gt;*&gt; mutable m_observers;
public:
void Attach(Observer<TAttribute&gt;&amp; observer) const
m_observers.push_back(&amp;observer);
void Detach(Observer<TAttribute&gt;&amp; observer) const
m_observers.erase(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0remove(m_observers.begin(), m_observers.end(), &amp;observer), m_observers.end());
void Notify(TAttribute&amp; attribute)
for (auto observer : m_observers)
observer-&gt;Observe(attribute);
class NodeA
public:
friend st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; operator<<(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; o, const NodeA&amp; node)
return o << "a";
class NodeB
public:
friend st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; operator<<(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; o, const NodeB&amp; node)
return o << "b";
class Parser
private:
Subject<NodeA&gt; m_subjectA;
Subject<NodeB&gt; m_subjectB;
public:
void Parse()
auto a = NodeA();
auto b = NodeB();
m_subjectA.Notify(a);
m_subjectB.Notify(b);
void Attach(Observer<NodeA&gt;&amp; observer)
m_subjectA.Attach(observer);
void Attach(Observer<NodeB&gt;&amp; observer)
m_subjectB.Attach(observer);
int main()
auto observerA = OutputtingObserver<NodeA&gt;();
auto observerB = OutputtingObserver<NodeB&gt;();
auto parser = Parser();
parser.Attach(observerA);
parser.Attach(observerB);
parser.Attach(observerA);
parser.Parse();
return 1;
You would need to use composition here and have a subject for each type of node. However, this is compile-time validated so I'd prefer this to the second version.
Solution #2: Dynamic and closer to what you want
#include <unordered_map&gt;
#include <vector&gt;
#include <algorithm&gt;
#include <iostream&gt;
class ObserverBase
public:
virtual ~ObserverBase() = default;
template<typename TAttribute&gt;
class Observer : public ObserverBase
public:
virtual void Observe(TAttribute&amp; attribute) = 0;
template<typename TAttribute&gt;
class OutputtingObserver : public Observer<TAttribute&gt;
public:
void Observe(TAttribute&amp; attribute)
st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0cout << attribute << st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0endl;
~OutputtingObserver() = default;
template<typename TKey&gt;
class Subject
private:
using ObserverList = st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0vector<ObserverBase*&gt;;
using ObserverMap = st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0unordered_map<TKey, ObserverList&gt;;
ObserverMap mutable m_observers;
public:
void Attach(TKey key, ObserverBase&amp; observer) const
auto itr = m_observers.find(key);
if (itr == m_observers.end())
{
m_observers.emplace(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0make_pair(key, ObserverList { &amp;observer }));
return;
}
itr-&gt;second.push_back(&amp;observer);
void Detach(ObserverBase&amp; observer) const
m_observers.erase(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0remove(m_observers.begin(), m_observers.end(), &amp;observer), m_observers.end());
template<TKey key, typename TAttribute&gt;
void Notify(TAttribute&amp; attribute)
auto itr = m_observers.find(key);
if (itr == m_observers.end())
return;
for (auto observer : itr-&gt;second)
dynamic_cast<Observer<TAttribute&gt;*&gt;(observer)-&gt;Observe(attribute);
enum class NodeType
TypeA,
TypeB
class NodeA
public:
friend st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; operator<<(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; o, const NodeA&amp; node)
return o << "a";
class NodeB
public:
friend st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; operator<<(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0ostream&amp; o, const NodeB&amp; node)
return o << "b";
class Parser
private:
Subject<NodeType&gt; m_subject;
public:
void Parse()
auto a = NodeA();
auto b = NodeB();
m_subject.Notify<NodeTyp75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0TypeA, NodeA&gt;(a);
m_subject.Notify<NodeTyp75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0TypeB, NodeB&gt;(b);
void Attach(Observer<NodeA&gt;&amp; observer)
m_subject.Attach(NodeTyp75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0TypeA, observer);
void Attach(Observer<NodeB&gt;&amp; observer)
m_subject.Attach(NodeTyp75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0TypeB, observer);
int main()
auto observerA = OutputtingObserver<NodeA&gt;();
auto observerB = OutputtingObserver<NodeB&gt;();
auto parser = Parser();
parser.Attach(observerA);
parser.Attach(observerB);
parser.Attach(observerA);
parser.Parse();
return 1;
This is closer to your version. Quite unsafe and slower but slightly less typing.
Summary
Both output a\na\nb and both are something sewn together just as a minimal proof of concept, not something you should follow (especially the working with unordered_map feels quite nasty).
It's not directly what you want but I guess that you can take it from there...
I have strong feeling that there are better solutions to this so feel free to experiment.
Solution #3: Completely dynamic
#include <unordered_map&gt;
#include <vector&gt;
#include <algorithm&gt;
#include <iostream&gt;
#include <typeinfo&gt;
#include <typeindex&gt;
template<typename TAttribute&gt;
class Observer
public:
virtual void Observe(TAttribute&amp; attribute) = 0;
virtual ~Observer() = default;
class Subject
private:
using ObserverList = st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0vector<void*&gt;;
using ObserverMap = st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0unordered_map<st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0type_index, ObserverList&gt;;
ObserverMap mutable m_observers;
public:
template<typename TAttribute&gt;
void Attach(Observer<TAttribute&gt;&amp; observer) const
auto index = st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0type_index(typeid(Observer<TAttribute&gt;));
auto itr = m_observers.find(index);
if (itr == m_observers.end())
{
m_observers.emplace(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0make_pair(index, ObserverList { &amp;observer }));
return;
}
itr-&gt;second.push_back(&amp;observer);
template<typename TAttribute&gt;
void Detach(Observer<TAttribute&gt;&amp; observer) const
m_observers.erase(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0remove(m_observers.begin(), m_observers.end(), &amp;observer), m_observers.end());
template<typename TAttribute&gt;
void Notify(TAttribute&amp; attribute)
auto itr = m_observers.find(st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0type_index(typeid(Observer<TAttribute&gt;)));
if (itr == m_observers.end())
return;
for (auto observer : itr-&gt;second)
static_cast<Observer<TAttribute&gt;*&gt;(observer)-&gt;Observe(attribute);
This is basically a ported C#'s version of Dictionary<Type, Object&gt;, it uses rtti so you might get spat on by C++ hardliners...
Comment for this answer: @YvesHenri I think that parser design in OOP should be Parser = factory, Node = core element with inheritance returned by the factory and the observer you have now should be node visitors... And that requires you to use pointers (st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0unique_ptr and st75b5:f2c1:f5d7:b954:8dc3:cee9:baf:a8c0make_unique are your friends). Unless you want to go C-style here, you'd not get away without pointers.
Another thing is the completely dynamic observer which is possible since C++11 and there are multiple ways of doing that. I will edit my answer if I get time for that...
Comment for this answer: I appreciate it. You did get my point. What I really want is to have observers dispatch objects of A-N-Y type: onNotify(T& t). There's a very similar thing: http://www.codeproject.com/Articles/3267/Implementing-a-Subject-Observer-pattern-with-templ. The following example shows to to notify the observers about a subject, but not something that's not a subject (if a node class does not inherit Subject, which is my case). If it's to have multiple types of subjects, I could simply have a single one and use my 'bad' example above. I'm really stuck. Or am I lost?
Comment for this answer: Continuing... Do you think it's not the case to make the parser a subject since another object will be waiting on it (observing) and add composition instead?! Are there any alternatives for the pointer problem I stated in the comments above?
Comment for this answer: Even thought your answer does not fully answers my question, I accepted it because of your effort and that it does kinda answer my question. Anyways, I ended up using inheritance, references and the oldschool type check for safe downcasts. It seems MUCH more straightforward, clean, beautiful and safe (I believe - and hope). :)


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 4, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2015:00:10/24/15', 'FavoriteCount': 1.0, 'PostTypeId': 1, 'Tags': '<c++><templates><c++11><observer-pattern><crtp>', 'Title': "Implementing the observer pattern using CRTP and 'anonymous types/template'", 'ViewCount': 747, 'id': 33320993, 'user_AboutMe': '<p>Someone who likes and tries to keep things simple, while also keeping clean and beautiful code.</p>\n', 'user_AccountId': 7122775.0, 'user_DisplayName': 'Henri', 'user_Reputation': 806.0, 'user_Views': 182.0, 'user_id': 5446775.0}}