21.1. Lightweight RAII
Sometimes we may find that a particular class does almost everything we want, but lacks that last little feature. This is the classic circumstance in which one chooses to inherit.
The STLSoft libraries define a performance counter class model. The UNIXSTL and WinSTL subprojects each define a class—performance_counter—that implements the functionality prescribed by the model. The classes have two epoch variables, representing the start and end of the measured interval. For efficiency reasons the member variables are not initialized in the constructor but are set via the start() and stop() methods, respectively. Under certain circumstances, however, it would be helpful to have the member state initialized upon construction.
This can easily be achieved using the STLSoft performance_counter_initialiser veneer. It is defined as follows:
Listing 21.1.
template <typename C>
class performance_counter_initialiser
: public C
{
public:
performance_counter_initialiser()
{
C::start(); // Initialise interval start member
C::stop(); // Initialise interval end member
}
};
The implementation is obvious and a classic veneer. It derives from its parameterizing type, and it adds nothing to the size of the parameterizing type. Instead it enhances the functionality provided by the parameterizing type: in this case initializing both epoch member variables to ensure that all subsequent calls on the instance will yield meaningful intervals. It can be applied to any class that conforms to a simple set of constraints, which is that the parameterizing type has a start() method and a stop() method, both of which take no nondefault parameters.
#ifdef WIN32
typedef winstl::performance_counter base_counter_t;
#else
typedef unixstl::performance_counter base_counter_t;
#endif /* operating system */
typedef performance_counter_initialiser<base_counter_t>
counter_t;
The functionality is provided in the constructor, wherein the method calls are qualified with the base class type C. This is to ensure that the parameterizing type has these methods. If the calls were not qualified in this way, the template could be applied to any type given the presence of free functions start() and stop().
|