Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limit a templated function to base and derived types?

Tags:

c++

templates

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.

like image 636
DanDan Avatar asked Nov 02 '11 21:11

DanDan


People also ask

How will you restrict the template for a specific datatype?

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.

What is a templated function?

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.

Can a template base class derived?

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.

What is the difference between typename and class in template?

There is no difference between using <typename T> OR <class T> ; i.e. it is a convention used by C++ programmers.


2 Answers

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.

like image 64
K-ballo Avatar answered Oct 06 '22 13:10

K-ballo


You are in an unusual situation out of which there is no "nice" way. You can:

  1. Check the type at runtime (or compile time, boost can probably do that)
  2. Take a 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.
  3. Do what K-ballo said.
like image 32
Seth Carnegie Avatar answered Oct 06 '22 12:10

Seth Carnegie