Suppose I have a template class with a lot of functions and I want to specialize them to change only a few of them and keep the other ones exactly as specified in the base template class.
How can I do that?
Below is what I want to achieve, but the solution isn't good, because it does not allow me to refer to the specialization for int
as Base<int>
– I need to use IntSpec
for that.
#include <iostream> using namespace std; template<typename T> struct Base { void print1() {cout << "Base::print1" << endl;}; void print2() {cout << "Base::print2" << endl;}; }; struct IntSpec : public Base<int> { void print2() {cout << "Base<int>::print2()" << endl;}; }; int main() { Base<double> d; // Base<int> i; <-- I want this kind of instantiation IntSpec i; d.print1(); d.print2(); i.print1(); i.print2(); }
The output is:
Base::print1 Base::print2 Base::print1 Base<int>::print2()
Inheriting from a template class is feasible. All regular inheritance and polymorphism rules apply. If we need the new derived class to be general, we must make it a template class with a template argument sent to the base class.
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
Templates provide sortability in a much nicer way, since the sortee doesn't need to know that it's being sorted. Complex inheritance typically results when you work with a forced mindset that everything must be an inheritance hierarchy, which is in fact rarely appropriate.
Templates can have more than one parameter type. Some older compilers allow one only to specialize either all or none of the template's parameters. Compilers that support partial specialization allow the programmer to specialize some parameters while leaving the others generic.
Nicol's solution works fine, but this is an alternative:
template<typename T> struct Base { void print1() {cout << "Base::print1" << endl;}; void print2() {cout << "Base::print2" << endl;}; }; template<> void Base<int>::print2() {cout << "Base<int>::print2()" << endl;};
That way you can specialize only specific member functions and still use those that you haven't specialized(in this case, print1
) without any problem. So now you'd use it just like you wanted:
Base<int> i; i.print1(); i.print2(); // calls your specialization
Demo here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With