I have a base class with a virtual function:
class Base
{
public:
virtual void Function();
};
void Base::Function()
{
cout << "default version" << endl;
}
and a derived template class:
template <class T> class Derived : public Base
{
public:
virtual void Function();
};
Is there a way to make Function()
be taken from the base class for all types, except some chosen ones? So what I want is to be able to define an overriden Function()
for, say, int
and long
:
void Derived<int>::Function()
{
cout << "overriden version 1" << endl;
}
void Derived<long>::Function()
{
cout << "overriden version 2" << endl;
}
and to have the default version of Function()
for all other types, without explicit definition of Function()
for them, so the output of
int main ()
{
Derived<int> derivedInt;
derivedInt.Function();
Derived<long> derivedLong;
derivedLong.Function();
Derived<double> derivedDouble;
derivedDouble.Function();
}
would be
overriden version 1
overriden version 2
default version
Is it possible?
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
You may overload a function template either by a non-template function or by another function template. The function call f(1, 2) could match the argument types of both the template function and the non-template function.
A template function can be overloaded either by a non-template function or using an ordinary function template.
A C++ template is a powerful feature added to C++. It allows you to define the generic classes and generic functions and thus provides support for generic programming. Generic programming is a technique where generic types are used as parameters in algorithms so that they can work for a variety of data types.
Member functions of class templates are in fact function templates, so you can specialize them:
template <typename T> class Foo
{
void Function();
};
template <typename T> void Foo::Function() { /* ... */ }
template <> void Foo<int>::Function() { /* ... */ }
Yes, by specializing Derived
.
Base
)Derived
to overrideSimple scheme, but it works.
First solution (use of the typeid
operator):
#include <iostream>
#include <typeinfo>
using namespace std;
class Base
{
public:
virtual void Function();
};
void Base::Function()
{
cout << "default version\n";
}
template<typename T>
class Derived : Base
{
public:
virtual void Function();
};
template<typename T>
void Derived<T>::Function()
{
if(typeid(T) == typeid(int)) // check if T is an int
{
cout << "overriden version 1\n";
}
else if(typeid(T) == typeid(long)) // check if T is a long int
{
cout << "overriden version 2\n";
}
else // if T is neither an int nor a long
{
Base::Function(); // call default version
}
}
int main()
{
Derived<int> di;
Derived<long> dl;
Derived<float> df;
di.Function();
dl.Function();
df.Function();
return 0;
}
I use the typeid
operator to check if T is either an int
or a long int
, and if it is, I print "overriden version [number]". If it is not, I call Base::Function()
, which will print "default version"
Note: to use the typeid
operator you need to include the header file typeinfo
Second solution (using template specializations):
// class declarations as before
template<typename T>
void Derived<T>::Function()
{
Base::Function(); // call default version
}
template<>
void Derived<int>::Function()
{
cout << "overriden version 1\n";
}
template<>
void Derived<long>::Function()
{
cout << "overriden version 2\n";
}
int main()
{
Derived<int> di;
Derived<long> dl;
Derived<float> df;
di.Function();
dl.Function();
df.Function();
return 0;
}
Here, I solve your problem with template specializations. If T is either an int
or a long int
, I call the specialized versions. Else, i call the general version, which is equivalent to Base::Function()
.
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