Observer pattern and virtual templated functions - c++

I am into a scenario that I have to (best thing I thought of) use virtual templated functions (for polymorphism), however, as far as I know, it is not possible.
I chose to 'use' virtual templated functions so I wouldnt need to use pointers and inheritance (for the observing part). My observable (subject) class is a Parser: it parses a XML file and is supposed to notify each observer about each node found. Every XML node is mapped into a class, for example:
// Maps the '?xml' tag
struct XML { int version; // other stuff... };
Instead, if I opted to use inheritance, I'd also have this class:
struct Node { // Probably blank? }
And then, the XML class would be as follows:
// Maps the '?xml' tag
struct XML : public Node { int version; // other stuff... };
I believe this would solve my problem, however I dont want to deal with pointers, since there would be a class (which I'm parsing the XML into) that has non-pointer attributes (nor I wish to make them pointers).
Here's how I implemented the observer pattern, with non-virtual templated functions. It does not work. Its just an example of how Id like it to be:
#include <iostream>
#include <vector>
enum Type { XML, // other xml tag types };
struct SomeXMLNode { int data; };
struct Observer {
// This is what Id like to make virtual
template<typename T>
void onObserved(T t, Type type)
{
std::cout << "[base] observing " << t.data << std::endl;
// 'Safely' cast t, according to the specified type
}
};
class Observable
{
public:
void attach(Observer* o) { observers.push_back(o); }
protected:
template<class Node>
void notify(Node node, Type type)
{
for (std::vector<Observer*>::iterator it = observers.begin(); it != observers.end(); it++) {
(*it)->onObserved(node, type);
}
}
Observable() {}
protected:
std::vector<Observer*> observers;
};
class Parser : public Observable
{
public:
void parse()
{
SomeXMLNode s;
s.data = 1234;
notify(s, Types::XML); // Notify all observers about 'some xml node' during the parsing
}
};
struct SomeLoadableClass : public Observer
{
void load()
{
Parser p;
p.attach(this);
p.parse();
}
template<typename T>
void onObserved(T t, Type type)
{
std::cout << "[derived] observing " << t.data << std::endl; // Will never(?) get called! :(
}
};
int main()
{
SomeLoadableClass m;
m.load();
return 0;
}
If inheritance were used, onObserved and notify functions could be changed to:
void onObserved(Node* node, Types type) { }
void notify(Node* node, Types type) { }
The 'Node' above is a struct, not the template I used in the other example.
Is the observer pattern even the best approach for this kind of task? Are there other choices without using inheritance? How could I get my derived class to dispatch the onObserved instead of the base class without declaring it virtual?

Since Parser derieves from Observable, the protected members should be accessible within Parser.
class Parser : public Observable
{
public:
void parse()
{
SomeXMLNode s;
s.data = 1234;
std::vector<Observer*>::iterator it = observers.begin();
for (;it != observers.end(); it++)
it->onObserved(s, Types::XML);
}
};

Related

how to extract template derived class's method into non-template base class

I want using polymorphism in C++, I am try to extract method shows in all derived class into base class.
For example:
I have two class, HouseA and HouseB, they are template class.
And they are derived from base class BaseHouse.
class BaseHouse
{
public:
//other thing
private:
};
template <typename Type>
class HouseA : public BaseHouse
{
public:
HouseA(Type object_input) : object(object_input)
{
}
// other thing about HouseA
Type &getObject()
{
std::cout << "this is House A" << std::endl;
return object;
}
private:
Type object;
};
template <typename Type>
class HouseB : public BaseHouse
{
public:
HouseB(Type object_input) : object(object_input)
{
}
// other thing about HouseB
Type &getObject()
{
std::cout << "this is House B" << std::endl;
return object;
}
private:
Type object;
};
Bacause of polymorphism, we using base class's pointer to access derivated class object. When I need to call method defined in derivated class, I am always transfer base class pointer into derivated class pointer:
int main()
{
HouseA<int> house_a(5);
int x = house_a.getObject();
BaseHouse *base_ptr = &house_a;
// suppose after some complicate calculate calculation
// we only have the base class pointer can access derivated class object
HouseA<int> *ptr_a = (HouseA<int> *)base_ptr; //transfer base class pointer into derivated class pointer
ptr_a->getObject();
return 0;
}
But the derived class HouseA and HouseB both have the method getObject.
So I want to extract template derived class's method into non-template base class.
For some reason, we suppose that the base class BaseHouse can not be template class.
Is there any way I can do that?
Thanks in advance.
If the signature of the derived member depends on the template arguments (as your getObject does on Type) the member cannot be extracted into a non-template base. At least not without removing the ability of the member's signature to vary based on template arguments.
Maybe not exactly a classical Visitor, but...
Okay, the basic idea is we have to somehow capture and encapsulate templated processing into a single entity ready-to-use in a run-time polymorphic construct.
Let's start with a simple class hierarchy:
struct Consumer;
struct Base {
virtual void giveObject(Consumer const &) const = 0;
virtual ~Base() = default;
};
struct Derived1: Base {
Derived1(int x): x(x) {}
void giveObject(Consumer const &c) const override {
c(x);
}
private:
int x;
};
struct Derived2: Base {
Derived2(double y): y(y) {}
void giveObject(Consumer const &c) const override {
c(y);
}
private:
double y;
};
So far, it is very simple: the Base class has a pure virtual method that accepts an object of type Consumer and a concrete implementation of this method is expected to expose to Consumer the relevant part of the internal state of its particular implementor (which is a subtype of Base). In other words, we have taken that 'virtual template' idiom and hid it inside the Consumer. Ok, what could it possibly be?
First option, if you know in advance at compile-time (at source code-time, more exactly) what it could possibly do, i.e. there's only one algorithm of consumption per each object type, and the set of types is fixed, it is quite straightforward:
struct Consumer {
void consume(int x) const { std::cout << x << " is an int.\n"; }
void consume(double y) const { std::cout << y << " is a double.\n"; }
template<typename T> void consume(T t) const {
std::cout << "Default implementation called for an unknown type.\n";
}
};
etc.
More elaborate implementation would allow run-time construction of a templated entity. How is that even possible?
Alexandrescu in his "Modern C++ Design" uses typeid to store particular type handlers in a single data structure. In a brief, this could be something like:
struct Handler {
virtual ~Handler() = default; // now it's an empty polymorphic base
};
template<typename T> struct RealHandler: Handler {
RealHandler(std::function<void(T)> f): f(std::move(f)) {}
void handle(T x) {
f(x);
}
private:
std::function<void(T)> f;
};
#include <map>
#include <type_info>
#include <functional>
struct Consumer {
template<typename T> void consume(T t) const {
auto f{knownHandlers.find(typeid(t))};
if(f != knownHandlers.end()) {
RealHandler<T> const &rh{
dynamic_cast<RealHandler<T> const &>(*f->second)};
rh.handle(t);
}
else {
// default implementation for unregistered types here
}
}
template<typename T> Consumer &register(std::function<void(T)> f) {
knownHandlers[typeid(T)] = std::make_unique<RealHandler<T>>(std::move(f));
}
private:
std::map<std::type_info, std::unique_ptr<Handler>> knownHandlers;
};
Haven't actually tested it, as I don't like typeids and other RTTI much. What I have quickly tested is another solution that requires neither maps nor typeinfo to store handlers in a templated manner. Still it uses a small trick, like how can we possibly pass, keep and retrieve information of an arbitrary type with the same call.
struct Consumer {
Consumer() {}
template<typename T> void consume(T t) const {
auto f{setSlot<T>()};
if(f) f(t);
else {
// default implementation for an unset slot
std::cout << t / 2 << '\n';
}
}
template<typename T>
std::function<void(T)> &setSlot(
std::function<void(T)> f = std::function<void(T)>{}) const
{
static std::function<void(T)> slot;
if(f) { // setter
slot = std::move(f);
}
return slot;
}
};
Here, setSlot() is used to store a handler for a particular type: when called with a non-empty argument, it stores that argument; and then returns its currently kept value. With Consumer so defined, the class hierarchy from above works as:
int main() {
Consumer c;
c.setSlot<int>([](int x){ std::cout << x << " is an int!\n"; });
Base const &b1{Derived1{42}};
Base const &b2{Derived2{3.14}};
b1.giveObject(c);
b2.giveObject(c);
}
Output:
42 is an int!
1.57
In the first line we see a message printed by a custom int handler; in the second line, a default message is printed for the double type, as no custom handler for double was installed.
One obvious drawback of this implementation is that handlers are stored in static variables thus all Consumers share the same handlers for all types, so Consumer here is actually a monostate. At least, you can change implementations for types at run-time, unlike if you had fixed Consumers of the very first approach. The maps-of-typeids approach from above shouldn't have this drawback, in exchange for some performance cost.

Design pattern for method returning different types/classes

This is a question for the Object Design Pattern specialists.
Let's assume I have a Parser class that is in charge of reading/parsing a stream of data (that carry information packets of different types). Each of these packets carry a different type of information, so ideally I would have a class for each type of packet (PacketTypeA, PacketTypeB, ... each one with its own interface).
class Parser {
public:
/* ctor */
/* dtor */
void read_packet(/* arguments */);
// methods...
private:
// more methods...
}
The method Parser::read_packet would then go through the stream and return a class (or pointer or reference to a class) to the appropriate packet type.
Would you use void pointers for this? How about a generic class (PacketBasicInterface) that would provide a common (partial) interface to query about the type of packet (so that any decision could then be made at runtime)?
// Pure virtual (abstract) class to provide a common (and partial) interface
class PacketBasicInterface {
public:
std::string whoAmI() const = 0;
bool amIofType(const std::string& type) const = 0;
}
// Class to access data of type A packet
class PacketTypeA : public PacketBasicInterface {
public:
// methodA_1()
// methodA_2(), ...
}
// Class to access data of type A packet
class PacketTypeB : public PacketBasicInterface {
public:
// methodB_1()
// methodB_2(), ...
}
Any thought or feedback would be very much appreciated!
Many thanks!
This is what std::variant is for.
I would define an enumeration class, that enumerates all possible packet types:
enum class packet_type {initialization_packet, confirmation_type, ... };
And have read_packet return a tuple of packet_type and a variant:
typedef std::variant< ... > packet_info;
std::tuple<packet_type, packet_info> read_packet();
Don't really need a formal enumeration, but it makes it easier to figure out what to do with the variant.
A few variations on this general approach include:
Using an opaque std::string, rather than a fixed enumeration, to specify the packet type.
Using std::any instead of a formal std::variant.
Instead of using a simple enumeration, or an opaque token like a std::string, use a slightly non-trivial class to define the packet type, with the class's methods taking the variant metadata as parameters, and encapsulating the operations that can be done on the packet.
Of course, as noted in the cited link, std::variant requires C++17. Which would be a good argument for you to update your compiler: you get a simple way to implement a completely type-safe approach.
Double dispatching can be the way to go if you are looking for a design pattern from the realm of object oriented programming.
It follows a minimal, working example:
#include<iostream>
struct Visitor;
struct PacketBasicInterface {
virtual void accept(Visitor &) = 0;
};
struct PacketTypeA: PacketBasicInterface {
void accept(Visitor &) override;
};
struct PacketTypeB: PacketBasicInterface {
void accept(Visitor &) override;
};
struct Visitor {
void visit(PacketTypeA) {
std::cout << "PacketTypeA" << std::endl;
}
void visit(PacketTypeB) {
std::cout << "PacketTypeB" << std::endl;
}
};
void PacketTypeA::accept(Visitor &visitor) {
visitor.visit(*this);
}
void PacketTypeB::accept(Visitor &visitor) {
visitor.visit(*this);
}
struct Parser {
PacketBasicInterface * read_packet() {
return new PacketTypeB{};
}
};
int main() {
Visitor visitor;
auto *packet = Parser{}.read_packet();
packet->accept(visitor);
delete packet;
}
Would you use void pointers for this?
No.
How about a generic class (PacketBasicInterface) that would provide a common (partial) interface to query about the type of packet (so that any decision could then be made at runtime)?
That makes most sense to me.
Let me refine that. Yes, it will be good to have a generic base class. However, when parsing the stream to construct sub-types of the base class, don't rely on an if-else type approach. Rather, use a factory pattern. Let the various factories construct the right object types based an on a key, which I assume will be available from the data being parsed.
If you encounter the string "PacketTypeA" in your data, you would expect that PacketTypeAFactory will be responsible for constructing the object.
FWIW, this approach is scalable for lots of sub-types of the base class. We use this approach at my work and it has served us well for over twenty years.
Here's the skeletal structure of the code base I am thinking of:
The classes.
class PacketBasicInterface { };
class PacketTypeA : public PacketBasicInterface { };
class PacketTypeB : public PacketBasicInterface { };
The interface of the factory.
// PacketFactory.h
class PacketFactory
{
public:
static PacketBasicInterface* makePacket(std::string const& packetData);
static void registerFactory(std::string const& key, PacketFactory* factory);
virtual PacketBasicInterface* make(std::string const& packetData) = 0;
virtual ~PacketFactory() {}
};
Implementation of the framework that makes the factory work.
// PacketFactory.cpp
#include "PacketFactory.h"
namespace PacketBasicInterface_Impl
{
using PacketFactoryMap = std::map<std::string, PacketFactory*>;
PacketFactoryMap& getPacketFactoryMap()
{
static PacketFactoryMap theMap;
return theMap;
}
};
uisng namespace PacketBasicInterface_Impl;
PacketBasicInterface* PacketFactory::makePacket(std::string const& packetData)
{
std::string key = extractKey(packetData);
PacketFactoryMap& theMap = getPacketFactoryMap();
PacketFactoryMap::iterator iter = theMap.find(key);
if ( iter == theMap.end() )
{
return nullptr;
}
return iter->second->make(packetData);
}
void registerFactory(std::string const& key, PacketFactory* factory)
{
getPacketFactoryMap()[key] = factory;
}
Code for making objects of type PacketTypeA using the factory pattern.
// PacketTypeAFactory.cpp
#include "PacketFactory.h"
#include "PacketTypeA.h"
class PacketTypeAFactory : public PacketFactory
{
public:
virtual PacketBasicInterface* make(std::string const& packetData)
{
PacketTypeA* packet = new PacketTypeA();
// Flesh out packet with data pulled from packetData
// ...
//
return packet;
}
struct Initializer
{
Initializer() { PacketFactory::registerFactory("PacketTypeA", new PacketTypeAFactory); }
};
};
// Constructing this object at static initialization time makes sure
// that PacketTypeAFactory is registered with PacketFactory when the
// stream data need to be parsed.
static PacketTypeAFactory::Initializer initializer;
The code for making objects of type PacketTypeB is very similar to the
code for making objects of type PacketTypeA using the factory pattern.
// PacketTypeBFactory.cpp
#include "PacketFactory.h"
#include "PacketTypeB.h"
class PacketTypeBFactory : public PacketFactory
{
public:
virtual PacketBasicInterface* make(std::string const& packetData)
{
PacketTypeA* packet = new PacketTypeA();
// Flesh out packet with data pulled from packetData
// ...
//
return packet;
}
struct Initializer
{
Initializer() { PacketFactory::registerFactory("PacketTypeB", new PacketTypeBFactory); }
};
};
// Constructing this object at static initialization time makes sure
// that PacketTypeBFactory is registered with PacketFactory when the
// stream data need to be parsed.
static PacketTypeBFactory::Initializer initializer;
Client code.
std::string packetData;
while ( getPacketData(packetData) )
{
PacketBasicInterface* packet = PacketFactory::makePacket(packetData);
if ( packet == nullptr )
{
// Deal with error.
}
else
{
// Use packet
}
}

Pattern for delegation to sub-component

In the product I am working, one of very basic scenario is serialization of classes. Typically a class to be serialized calls serialization on its sub-component
e.g. if there is a class s.t. class
A{B;C;D;} then A.Pack will call pack
function on B,C,D.
Since there are many such classes, same pattern of code has to be duplicated over and over again.
Is it possible to encapsulate this behavior in a pattern (possibly using templates and inheritance)
The usual way of making a template do this is to use a type list:
#include <iostream>
// typelist definition
struct Empty {};
template < typename H, typename T = Empty >
struct Cons {
typedef H head;
typedef T tail;
};
// interfaces all items support
class IPack
{
public:
virtual void Pack() = 0;
};
// some packable items
class Fee : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fee\n";
}
};
class Fi : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fi\n";
}
};
class Fo : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fo\n";
}
};
class Fum : public IPack
{
public:
virtual void Pack() {
std::cout << "Packed Fum\n";
}
};
// these two templates create a composite IPack from a list
// of the types of its parts
template <typename Types>
class PackList : public PackList<typename Types::tail>
{
protected:
typedef typename Types::head Item;
Item item;
public:
virtual void Pack() {
item.Pack();
PackList<typename Types::tail>::Pack();
}
};
template <>
class PackList<Empty> : public IPack
{
public:
virtual void Pack() {}
};
// FeeFiFoFum is a composite of four items
class FeeFiFoFum : public PackList<Cons<Fee,Cons<Fi,Cons<Fo,Cons<Fum> > > > >
{
};
// create a FeeFiFoFum and call pack on it, which calls pack on its parts
int main ()
{
FeeFiFoFum giant;
giant.Pack();
}
Proper implementations of composites created from type lists give you accessors for the members and so on, but this is enough to show how they works, and prints out that it packed Fee, Fi, Fo and Fum without specifying any behaviour.
One possible design that would help accomplish this is to use the Composite pattern. Your Component (to borrow from the Wikipedia drawing) is Packable, which would implement a Template Method Pack() that can do something like so:
GetChildren();
for each child:
child.Pack()
PackImpl();
PackImpl() is a pure virtual method in Packable, and all classes that inherit implement it appropriately. GetChildren() would return an STL container (possibly empty), for iteration. It can be implemented in Packable, along with a private member collection to store the child objects. Basically, you then inherit all the classes from Packable, implement PackImpl(), and you're done.
Note that this will cause issues if your inheritance hierarchy depends on the child pieces being members directly. If you've approached the problem in terms of aggregation, this should work well.
It's possible that the Visitor pattern may help.
http://en.wikipedia.org/wiki/Visitor_pattern
The idea of this is to separate the traversal logic (stepping through your objects) from the handling of each object. In this case, the per-object logic is serializing (encoding) a single object (or deserializing, of course). This should be fairly simple and minimally repetitive using normal OOP techniques.
Implementing the traversal and the Visitor-pattern specific code is annoying, but it's mostly boilerplate and should be a one-off thing.
One commenter wrote:
If you mean "is there a way I can write a template to automatically call a method on each of my member variables?", then the answer is no...
My (slightly evil) counter to that is yes, if the method is the destructor...
#include <iostream>
using namespace std;
bool Enable = false;
template <typename T>
class DS : public T {
public:
~DS() {
if (Enable) T::Serialize();
}
};
class A {
protected:
void Serialize() { cout << "A" << endl; }
};
class B {
protected:
void Serialize() { cout << "B" << endl; }
};
typedef DS<A> DSA;
typedef DS<B> DSB;
class C {
protected:
void Serialize() { cout << "C" << endl; }
private:
DSA a;
DSB b;
};
typedef DS<C> DSC;
int
main()
{
DSC c;
{
DSC c_copy = c;
Enable = true;
}
Enable = false;
}
The output is in reverse order, so to reconstruct objects you'd have to parse the serialized data and push each completed object on a stack. Composite objects would then know how many children to pop off of the stack. Or, of course, the serialization could go to an intermediate structure.
Another intriguing idea would be to use this hack once at startup (create and destroy only one special object) where the callbacks from the destructors would create a data structure that described the original object.
I also note that implicit copy constructors have potential for similar abuse, and possible in forward order...

How pass data to 'generic' observer? As arguments or as a single struct?

I am busy adding a generic observer mechanism to a legacy C++ application (using Visual Studio 2010, but not using .Net, so .Net delegates are out of the question).
In the design I want to separate the application-specific part as much as possible from the generic observer mechanism.
The most logical way of implementing observers seems this way:
class IDoThisObserver
{
public:
void handlDoThis(int arg1, int arg2) = 0;
};
For every type of observer (IDoThisObserver, IDoThatObserver, ...) the arguments of the methods (handleDoThis, handleDoThat) are different.
What remains in a generic way of storing the observers, like this:
template<typename T>
class ObserverContainer
{
public:
void addObserver (T &t) {m_observers.push_back(&t);}
private:
std::list<T*> m_observers;
};
Calling an observer can't be generalized since the arguments are different for every observer type.
An alternative way would be to 'pack' all arguments into one argument, like this:
struct DoThisInfo
{
DoThisInfo (int arg1, int arg2) : m_arg1(arg1), m_arg2(arg2) {}
int m_arg1;
int m_arg2;
};
And then define a more generic observer, like this:
template<typename T>
class IObserver
{
public:
void notify(const T &t) = 0;
};
And a collection of these observers would then become this:
template<typename T>
class ObserverContainer
{
public:
void addObserver (IObserver<T> &obs) {m_observers.push_back(&obs);}
private:
std::list<IObserver<T>*> m_observers;
};
Now, much more logic can be centrally added to this ObserverContainer, including calling all observers. The 'initiator' of the call only needs to create and fill in the notification structure.
Classes that want to inherit from multiple kinds of observers, need to do it like this:
class MyObserver : public IObserver<NotifyThis>, public IObserver<NotifyThat>
{
...
};
Which of these approaches (observers with multiple explicit arguments or with one struct argument) seems the best? Are there any advantages or disadvantages to either of these approaches?
EDIT: I looked a bit further to alternative approaches, and the Slot/Signal approach seems another good candidate. Are there any important disadvantages in Slot/Signal that I should know of?
Why not just do:
class IObserver {
// whatever is in common
};
class IDoThisObserver : public IObserver
{
public:
void handlDoThis(int arg1, int arg2) = 0;
};
class IDoThatObserver : public IObserver
{
public:
void handlDoThat(double arg1) = 0;
};
?
Then you have:
class ObserverContainer
{
public:
void addObserver (IObserver* t) {m_observers.push_back(t);}
private:
std::list<IObserver*> m_observers;
};
The design with the struct argument is definitely better as it allows for generic code to be written in the ObserverContainer. It's generally a good design practice to replace longish argument lists with objects that encapsulate the arguments and this is a good example of the payoff. By creating a more general abstraction for your notify method (with the struct you're defining notify as a method that takes a chunk of "data" whereas with the arg list you're defining a method that takes two numbers) you allow yourself to write generic code that uses the method and doesn't have to concern itself with the exact composition of the passed in chunk of data.
Have you looked into Boost.Signals? Better than to reimplement the wheel.
As for Parameters: Calling an observer/slot should conceptionally be the same as if you would call an ordinary function. Most SignalSlots-Implementations allow multiple Parameters, so use it. And please use different signals for different observer types, then there is no need to pass around data in Variants.
Two Disadvantages of the Observer-Pattern/SignalSlots i have seen:
1) Program flow is difficult or even impossible to understand by looking only at the source.
2) Heavily dynamic programs with lots of Observers/SignalSlots may encounter a "delete this"
Everything aside, i like Observers/SignalSlots more than subclassing and thus high coupling.
I don't think either of your approaches would fit your requirement as is. However a little modification using a DataCarrier containing the dataset passed across all the observers wherein each observer would know what to read would do the trick. The sample code below might clear it (note i have not compiled)
enum Type {
NOTIFY_THIS,
NOTIFY_THAT
};
struct Data {
virtual Type getType() = 0;
};
struct NotifyThisData: public Data {
NotifyThisData(int _a, int _b):a(_a), b(_b) { }
int a,b;
Type getType() { return NOTIFY_THIS; }
};
struct NotifyThatData: public Data {
NotifyThatData(std::string _str):str(_str) { }
std::string str;
Type getType() { return NOTIFY_THAT; }
};
struct DataCarrier {
std::vector<Data*> m_TypeData;
};
class IObserver {
public:
virtual void handle(DataCarrier& data) = 0;
};
class NotifyThis: public virtual IObserver {
public:
virtual void handle(DataCarrier& data) {
vector<Data*>::iterator iter = find_if(data.m_TypeData.begin(), data.m_TypeData.end(), bind2nd(functor(), NOTIFY_THIS);
if (iter == data.m_TypeData.end())
return;
NotifyThisData* d = dynamic_cast<NotifyThisData*>(*iter);
std::cout << "NotifyThis a: " << d->a << " b: " << d->b << "\n";
}
};
class NotifyThat: public virtual IObserver {
public:
virtual void handle(DataCarrier& data) {
vector<Data*>::iterator iter = find_if(data.m_TypeData.begin(), data.m_TypeData.end(), bind2nd(functor(),NOTIFY_THAT);
if (iter == data.m_TypeData.end())
return;
NotifyThatData* d = dynamic_cast<NotifyThatData*>(*iter);
std::cout << "NotifyThat str: " << d->str << "\n";
}
};
class ObserverContainer
{
public:
void addObserver (IObserver* obs) {m_observers.push_back(obs);}
void notify(DataCarrier& d) {
for (unsigned i=0; i < m_observers.size(); ++i) {
m_observers[i]->handle(d);
}
}
private:
std::vector<IObserver*> m_observers;
};
class MyObserver: public NotifyThis, public NotifyThat {
public:
virtual void handle(DataCarrier& data) { std::cout << "In MyObserver Handle data\n"; }
};
int main() {
ObserverContainer container;
container.addObserver(new NotifyThis());
container.addObserver(new NotifyThat());
container.addObserver(new MyObserver());
DataCarrier d;
d.m_TypeData.push_back(new NotifyThisData(10, 20));
d.m_TypeData.push_back(new NotifyThatData("test"));
container.notify(d);
return 0;
}
This way u need to modify only the enum if u add a new structure.
Also u can use boost::shared_ptr to handle the mess of pointers.
I wouldn't get the syntax right so I'm just going to list the declarations to illustrate the structures. A generic Observer could be made to expect a parameter that is either subclassed to specific forms of your required parameters or is struct including a horizontal mapping of all primitive parameters that will be required by your Observers. Then the ObserverContainer could function as an AbstractFactory and each subclass of the ObserverContainer could be DoThatObserverFactory and DoThisObserverFactory. The factory would build an observer and assign a configuration to the observer to tell it which parameter to expect.
class AbstractObserverFactory {...};
class DoThatObserverFactory : AbstractObserverFactory {...};
class DoThisObserverFactory : AbstractObserverFactory {...};
class ObserverParam {...};
class DoThatObserverParam : ObserverParam {...};
class DoThisObserverParam : ObserverParam {...};
class Observer;
class DoThisObserver : public Observer
{
public:
void handlDoThis(DoThisObserverParam);
};

C++ visitor pattern handling templated string types?

I'm trying to use the visitor pattern to serialize the contents of objects. However one snag I'm hitting is when I'm visiting strings. My strings are of a templated type, similar to STL's basic_string. So something like:
basic_string<char_type, memory_allocator, other_possible_stuff> \\ many variations possible!
Since I can have very many different templated string types, I can't go and add them to my visitor interface. It would be ridiculous. But I can't add templates to my VisitString method because C++ prevents using templates parameters in virtual methods.
So what are my options to work around this?
EDIT: I've added some basic code
class IVisitor
{
public:
virtual void VisitString(some_kind_of_string_type string) = 0; // this is what I want in theory
};
class MyObject
{
public:
typedef basic_string<char8, myAllocator, some_flag> MyStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(mString);
}
private:
MyStringType string;
};
class MyOtherObject
{
public:
typedef basic_string<char16, myOtherAllocator, some_other_flag> MyOtherStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(mString);
}
private:
MyOtherStringType string;
};
class Reader : public IVisitor
{
public:
virtual void VisitString(some_kind_of_string_type string)
{
// read some data, give it to the string
}
}
Do you need runtime polymorphism?
struct object {
template <typename Visitor>
void accept( Visitor & v )
{
v( x );
v( a );
}
int x;
std::string a;
};
struct complex_object {
template <typename Visitor>
void accept( Visitor & v ) {
v( i );
o.accept(v); // [1]
}
int i;
object1 o;
};
struct DumpScreenVisitor {
void operator()( int x ) { std::cout << x << std::endl; }
template <typename char_t, typename traits_t, typename alloc_t>
void operator()( std::basic_string<char_t, traits_t, alloc_t> const & str )
{
std::cout << str << std::endl;
}
};
The call in [1] can be converted into v( o ) with a generic templated operator() in the visitors that is the least specialized:
template <typename O>
void DumpScreenVisitor::operator()( O & o )
{
o.accept( *this );
}
But this can interfece with other visitor implementations (for example, the above visitor can be implemented with a single templated method):
struct DumpScreenVisitor {
template <typename T>
void operator()( T const & t ) {
std::cout << t << std::endl;
}
};
So at the end you will have to compromise in either way.
This approach is similar to the boost::variant visitor implementation (you may want to take a look at it), with the difference that the boost::variant is a single class and not a hierarchy.
In the end, I went with a slightly different approach. Instead of hoping to use a visitor with templated methods (which is, of course, impossible), I decided to pass a visitor-like class as a template parameter to my object's visit method. Totally simplified example:
class SomeKindOfVisitor // doesn't need to derive from a base class.
{
template <class StringClass>
void VisitString(StringClass& string) // I get to keep templated methods
}
class MyObject
{
typedef basic_string<char8, myAllocator, some_flag> MyStringType;
public:
template <class VisitorClass>
void Accept(VisitorClass& visitor)
{
vistior.VisitString<MyStringType>(mMyString);
}
private:
MyStringType mMyString;
}
With this method, I still get to use my templated strings while still being able to pass any kind of "visitor" to my objects.
your visitor should handle only a basic representation of strings (char* / wchar*);
it is then up to the accept method to process the cast.
Well, the question is, of the template parameters on your string can be so different, can you apply one single serialization method for them? If so, you could write an adapter that has a templated constructor that extracts all the information needed for serialization into a uniform representation. Then you visit the serializer with the adapter.
EDIT: After you added you code, I still think that an adapter could solve your problem, only the other way around. In you Accept-method, construct a local adapter and pass it to the Visitor. When the Visitor has modified it, you can use a template method extractToString on the adapter that converts the information to a specific string version. This may make the adapter quit complex, depending on how different the string-template instantiations have to be handled.
Since all your string classes are of different types, you will need some level of compromise (either a common sub-type, with virtual methods, for your strings, or an adapter, or adding a method for each different type to the visitor). Mixing generic-programming and oo can be a pain, especially if you don't accept compromises.
Eg.
class string_tag { /* common visitor interface */ };
template<typename char_t, ...> class basic_string : public string_tag {};
class IVisitor
{
public:
virtual void VisitString(string_tag& string) = 0; // this is what I want in theory
};
class MyObject
{
public:
typedef basic_string<char8, myAllocator, some_flag> MyStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(string);
}
private:
MyStringType string;
};
class MyOtherObject
{
public:
typedef basic_string<char16, myOtherAllocator, some_other_flag> MyOtherStringType;
Accept(IVisitor* visitor)
{
visitor->VisitString(string);
}
private:
MyOtherStringType string;
};
class Reader : public IVisitor
{
public:
virtual void VisitString(string_tag& string)
{
// read some data, give it to the string
}
}
May be you can consider below, but in this case you need to separate visitor mechanisms to different visitor classes. WStringVisitor and StringVisitor are just examples for different Visitor semantics.
#include <string>
#include <iostream>
using namespace std;
template <typename stringType>
class IVisitor{
public:
virtual void visit(stringType _string)=0;
};
class StringVisitor: public IVisitor<string>{
public:
void visit(string str){
cout<<"This is std::string implementation: "<< str << endl;
}
};
class WStringVisitor: public IVisitor<basic_string<wchar_t>>{
public:
void visit(basic_string<wchar_t> str){
//wprintf(L"This wide implementation : %S", str.c_str());
wcout<<"This is WString Visitor: "<< str << endl;
}
};
class MyObject{
public:
typedef basic_string<char> MyStringType;
void accept(IVisitor<MyStringType>& visitor){
visitor.visit("TEST STRING");
}
};
class MyOtherObject
{
public:
typedef basic_string<wchar_t> MyOtherStringType;
void accept(IVisitor<MyOtherStringType>& visitor)
{
visitor.visit(L"TEST WSTRING");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyObject acceptor;
MyOtherObject otheracceptor;
StringVisitor visitor;
WStringVisitor wvisitor;
acceptor.accept(visitor);
//otheracceptor.accept(visitor); compile error
otheracceptor.accept(wvisitor);
return 0;
}
I think the fundamental problem here is that the Visitor pattern is all about virtual functions, while you herd your strings through function templates. And these just don't easily mix. In fact, the only way I can think of to mix the two is type erasure.
If you don't find a way to do what you want using this technique, I don't think you'll find a way.