There are probably many of you out there who, like me, have investigated the possibilities that templates and template meta-programming can bring to your code.
After having some success with templated image and image algorithm classes, I turned my attention to seeing whether some of the design patterns I use could be encapsulated in the same way. Investigation on the web revealed that template meta-programming could play a part in achieving this.
An article on Dr Dobbs introduced me to typelists and some of the meta-programming techniques, with the Visitor pattern used as an example.
Unfortunately, I soon found that Visual C++ was not entirely happy with the syntax used and it took some time before I managed to get a version that didn’t give the compiler indigestion! That didn’t last long, though. Instantiating my first Visitor object caused the compiler to generate the dreaded “Internal compiler error. Try simplifying your code”. Well, I gave up at that point, deciding I had better things to do with my life than battling my compiler. So, I decided to try and achieve the similar objective to the Visitor example without meta-programming.
Anyone unfamiliar with the Visitor pattern should read this first.
The objective of the Dr Dobbs example was merely to remove a small amount of boilerplate code and ensure that all handling omissions in all code would be flagged at compile time.
The use of this technique in the Visitor pattern may seem somewhat trivial, but I hope that you may find the methods used useful in more complex situations, despite it not being as ‘cool’ as using typelists and meta-programming.
How It Works
The purpose of these classes is to create a Visitor base class with pure virtual Visit functions for each supplied type. Any derived class that tries to instantiate an object from it will then be forced to supply an overridden version for each and every Visit function.
Similarly the Visitable class defines pure virtual Accept function for each supplied visitor type.
The framework is based on two template classes; Visitor & Visitable.
Classes that should be visitable should derive from the Visitable template class. The classes that may visit should be defined in the template type parameter list.
Here I have defined a template and specialisations to accept up to 4 visitor types.
Classes that should be able to visit visitable classes should derive from the Visitor template class. The types that the visitor expects to support should be defined in the template type parameter list.
Here I have defined a template and specialisations to accept up to 16 types types. It may seem like it would be an onerous task to modify this to accept any N types, but the repetitive nature of the code lends itself perfectly to generation via a script.
How It’s Used
I’ll use the good old ‘Shape’ example so loved by many.
First, you create the base for your ‘Shape’ visitor.
Then, you define the ‘Shape’ base class. It derives from the Visitable class that defines a pure virtual ‘Accept’ function that accepts a ShapeVisitor.
Next, you define the shapes ‘Square’, ‘Circle’, and ‘Triangle’. Each overrides the ‘Accept’ function that calls the visitor with itself as a parameter.
Now that you have the framework in place, you can do something with it. Here’s an example that creates ‘Draw’ and ‘Serialise’ visitors and applies them to a vector of Shape objects.
Now we define the actual visitors and a container for shapes.
The following is a utility function to apply a visitor to the list of shapes.
And now the code to test in all.
The output from the example is as follows…
Draw the square Draw the circle Draw the triangle Serialise the square Serialise the circle Serialise the triangle
A version of this framework can be found as part of the Embedded Template Library, an open source C++ library distributed under the MIT licence.