One option that may work well is the following: each parser class defines methods with the same signatures, but does it completely independently of each other's class. Then enter the hierarchy of the secondary class, which actually implements all these functions, then redirects the call of each method to a specific parser object. Thus, the implementation of the analyzer receives all the advantages of inlining, since from the point of view of the class all calls can be solved statically, while the client receives the benefits of polymorphism, since any method call will dynamically decide the correct type.
The trick here is that you use additional memory (the wrapper object takes up a space), and you will also probably have at least one additional indirect action when you call the parser functions, since the call goes
client -> wrapper -> implementation
Depending on how rarely you call methods from the client, this implementation may work very well.
Using templates, you can implement a shell layer extremely concisely. The idea is this. Suppose you have methods fA, fB and fC. Start by defining a base class as follows:
class WrapperBase { public: virtual ~WrapperBase() = 0; virtual void fA() = 0; virtual void fB() = 0; virtual void fC() = 0; };
Now define the following template type as a subclass:
template <typename Implementation> class WrapperDerived: public WrapperBase { private: Implementation impl; public: virtual void fA() { impl.fA(); } virtual void fB() { impl.fB(); } virtual void fC() { impl.fC(); } };
Now you can do something like this:
WrapperBase* wrapper = new WrapperDerived<MyFirstImplementation>(); wrapper->fA(); delete wrapper; wrapper = new WrapperDerived<MySecondImplementation>(); wrapper->fB(); delete wrapper;
In other words, all the shell code can be generated for you by the compiler, simply by creating an instance of the WrapperDerived template.
Hope this helps!
templatetypedef
source share