Simulated partial Specialization for C++
Today much of the current C++ literature laments the lack of widespread compiler support for partial template specialization. There are some well known workarounds, but they tend to be of limited applicability. We are currently employing a "simulated partial specialization" technique that applies to a broader range of problems. In particular allows specialization of template classes for pointer types. One interesting application is to allow improved STL implementations on non-compliant compilers. The following code was tested on Microsoft Visual C++ 6 service pack 3. In this toy example we present a simple vector class which is specialized for pointer types. The template metaprogramming techniques used support simulation of other partial specialization features, e.g. holding one or more template parameters fixed, as well as a kind of poor man's typeof. We have enjoyed some success applying these techniques to a larger STL-style generic container library.
Here is an outline of the idea. We make use of the IF template metafunction (or SWITCH if there is more than one specialization) and the sizeof operator.
IF --- IF is actually a template struct based on a bool and two type parameters - IF<bool, IfType, ElseType>. It 'returns' the appropriate type via the RET typedef where RET stands for return.
sizeof --- we recently learned of the flexibility of the sizeof operator.In particular sizeof can accept a function expression without evaluating the function. We declare (but do not define) a pair of discriminating functions to determine if a specialization applies. In the case of pointers we (essentially) use
char IsPtr(const volatile void*);
We convert this pair of discriminating functions into a template metafunction ISPTR<T>. That is, ISPTR <T> returns true in the RET enum if and only if T is a pointer type. Finally this allows us to write IF<ISPTR<T>::RET, PointerSpecialized<T>, Unspecialized<T> >::RET to achieve simulated partial specialization where PointerSpecialized is the specialized version of the type and Unspecialized is the general case. By varying these discriminators we can specialize on other criteria.
As stated above we can generalize this technique using the SWITCH metafunction and more than two discriminating functions. For example we might define a discriminating metafunction SPECIALIZER which returns an int rather than a bool. Than the simulated specialization would look like
CASE<DEFAULT, GENERAL_CASE<T> >::RET
Needless to say it is possible to discriminate on more than one template parameter.
Mat Marcus and Jesse Jones, September 2000
Version 1.0 is available for download.
What's New in Version 1.0