I have a template base class like this:
template<typename T, std::size_t Size>
class VectorT
{
public:
typedef T data_type;
}
and a few specialised derived classes:
template<typename T>
class Vector2d : public VectorT<T, 2U>
{ // some specialised functions }
template<typename T>
class Vector3d : public VectorT<T, 3U>
{ // some other specialised functions }
and these work fine. Howerver, I have a few free-standing functions for operators. For example:
template<typename T, size_t Size>
VectorT<T, Size> operator*(T lhs, const VectorT<T, Size>& rhs)
{
...
}
Unfortunately these do not work for my derived classes, because they return a VectorT<T, Size>
instead of a Vector2d<T>
.
So I tried with
template<V>
V operator*(typename V::data_type lhs, const V& rhs)
{
...
}
and this works fine, however it can lead to ambiguities because it sucks in anything else with a data_type member.
How can I get around this: how can I write type safe functions that only work with my vector base, or any derivatives of?
I am trying to get around having to re-declare and redefine the operators again for the subclasses.
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.
Function templates are similar to class templates but define a family of functions. With function templates, you can specify a set of functions that are based on the same code but act on different types or classes.
It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
There is no difference between using <typename T> OR <class T> ; i.e. it is a convention used by C++ programmers.
You could add yet another base class, one that is independent of the template parameters, and use SFINAE to disable calls for types other than derived from such base:
struct VectorBase {};
template< typename T, std::size_t Size >
class VectorT : public VectorBase { ... }
template< typename V >
typename boost::enable_if< boost::is_base_of< VectorBase, V >, V >::type
operator*( V lhs, V const& rhs ){ ... }
Note that is_base_of< X, X >
is always true
, so this function will work for one more type than required, namely the base class VectorBase
.
If you are using a compiler that implements TR1, you can replace boost::
for std::
in both places where is used.
You are in an unusual situation out of which there is no "nice" way. You can:
VectorT<>&
and use that instead of creating a new VectorT
inside the function and returning it. This way you can take subclasses of VectorT
by reference as well. That would make you have to use a function instead of an operator though.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