Precaution: Basic knowledge on C++ templates needed
Recently, once of my friend, Amal asked me to share if I know any methods to restrict the types to instantiate a template class. Which means that, suppose, if you have written some classes to support only floating types like double, float etc… and want to other types like, int, long or any other types. Or if you support a certain kind of data, it will affect the core logic used in that, in that case you may have to restrict the data type for you class.
Amal described his idea. It goes as follows. (I’ve modified the code a bit make it comfortable for me J. You can see the original post in his blog)
template <class T>
class CTest
{
void AssertType( float& f ) const{ } // Allow Type double
// If you want to add more, add with the same signature
public:
CTest()
{
// Here goes the compilation error
T validate;
AssertType( validate );
};
};
int main(int argc, char *argv[])
{
CTest<float> t;
CTest<int> er; // Error: Invalid Type
return 0;
}
When we discussed about this, I got an idea using template specialization. The disadvantage of my method is that, it will not show any kind of compilation error, but linking error. In method one, we have additional cost of instantiating a temporary object for type checking. If the classes design to support primitive data types, no needs to worry, it will not cost any kind of performance overhead. Trust me J. Both methods will support inheritance of the data types.
Anyway let me introduce my method.
template <class T>
class CTest
{
public:
CTest();
};
template <> CTest<double>::CTest()
{
cout << “Test”;
}
int main(int argc, char *argv[])
{
CTest<int> t;
return 0;
}
The above method is implemented using template specialization. The ctors are allowed only for allowed type. Basicsally both methods are doing the same thing but in different way. If you use the second method you can avoid a temporary object to assert the type data it’s going to support.
There’s one more disadvantage for all of the above method, suppose your want to support both float and double, you will have to specialize ctors with both float and double(using method 2) and two overloaded functions AssertType function is needed.
Ok let me do some more far thinking to support compatible types without writing additional code. I think it’s better to take method 1 for modification.
void AssertType( const double& f ) const{ } // Allow Type double
What if you put a const in front of the parameter? What would happen? Now the compiler will support both double and float. Or in other words, it will try to type case the type we passing to the class to call the AssertType function. But alas!!! It will also support int type with a warning. So not always we can achieve the conversion using this method because of compiler will automatically convert between types. One more thing all the above methods support Inherted types. i.e If you allow base class type, surely it will also support derived class type also J
What you guys think? Is there any better Idea? Please share with me if possible.
[I am using Calibri and Consolas Font for blogging: for better viewing, download it from Microsoft website]