How to do this using templates in C++

Started by
31 comments, last by deathkrush 17 years, 9 months ago
I'm writing a Vector and Matrix library and the problem I stumbled upon is the fact that every Vector2, Vector3 and Vector4 needs to be defined as a separate class, even though the functions are all the same, they just use a different number of data members. I was just thinking that maybe there was a way to use templates, macros or inheritance to reuse some of that code. Is this possible using templates:

template <class T, int n>
class Vector
{
	T x;
	T y;
$if(n>=3) //just kidding, I WISH there was a keyword like that
	T z;
$endif
$if(n==4)
	T w;
$endif
};

I tried doing this, but partial template specialization requires that I redefine the class every time, so it's kind of pointless:

template <class T, int n>
class Vector
{
	T data[n];
};

template <class T, int n>
class Vector<T, 2>
{
	T data[n];
	Vector(T _z, T _y);
};

template <class T, int n>
class Vector<T, 3>
{
	T data[3];
	Vector(T _x, T _y, T _z);
};

Did anybody have this issue, and if so, how did you solve it? Thanks.
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
Advertisement
With me i had so many problems with C++ that i changed over to C# language. even though its almost the same thing but it is easier to use C#, you also should get alot less problems for your "Vector and Matrix library". i hope this will help.
Jer
via explicit instantiation. A code generator could help the tedium, but there's no template magic I know of to get that working.
I specialised the classes, using the little anonymous union/struct trick:

template <typename T> SVector<3, T>{	union	{		struct		{			T x, y, z;		};		T mElements[3];	};};


Now, since each specialisation has a member called mElements, I can make friend functions/operators of the unspecialised class without needing to rewrite them. In the above, Any SVector<3> has members x y and z, but SVector<253> won't (my SVector<2> specialisation has x and y, and my SVector<4> has x y z w). If that makes any sense. I can divulge source code if it helps.
[ search: google ][ programming: msdn | boost | opengl ][ languages: nihongo ]
I would make two suggestions (although neither may be to your liking).

First, look at how the standard library does it. Those guys are pretty clever. Examine, for instance, the std::valarray class.

Second, I would suggest (and I don't do this lightly) using inheritance. Yes, you'll have to duplicate some code, but most functions can be moved into a templated base class.

template<typename T, int n>  class VectorBase  {  public:    VectorBase operator+=(const VectorBase& rhs)    {      for (int i = 0; i < n; ++i)      {        m_data += rhs.m_data;      }      return *this;    }    // other operations...  protected:    T m_data[n];  };template<typename T>  class Vector2: public VectorBase<T, 2>  {  public:    Vector2(T x, T y) { i/* ... */ }  };template<typename T>  class Vector3: public VectorBase<T, 3>  {  public:    Vector3(T x, T y, T z)    { this->m_data[0] = x; this->m_data[1] = y; this->m_data[2] = z; }  };main(){  Vector3<int> v0(0, 0, 0);  Vector3<int> v1(1, 1, 1);  v1 += v0;}

Stephen M. Webb
Professional Free Software Developer

My vector class is similar. It is parametised by the type of the elements and the number of elements. I had to specialise the vector for sizes 2, 3 and 4 to define the x, y, z and w members and define an operator[]. Then all other operators and functions were made non-member non-friends, and operated on vectors of all sizes generically by using the size template parameter and looping through all elements via operator[]. These loops are optimized out by the compiler.
Quote:Original post by _goat
Now, since each specialisation has a member called mElements, I can make friend functions/operators of the unspecialised class without needing to rewrite them.


That sounds like a great idea. Can you provide an example how to reuse code using friend functions? So far my impression of partial specialization was that for each specialized template I have to rewrite everything.

Quote:Original post by Bregma
First, look at how the standard library does it. Those guys are pretty clever. Examine, for instance, the std::valarray class.

Second, I would suggest (and I don't do this lightly) using inheritance. Yes, you'll have to duplicate some code, but most functions can be moved into a templated base class.


Templates and inheritance... that's pretty clever, I'll try it. Thanks.
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
Quote:Original post by _goat
I specialised the classes, using the little anonymous union/struct trick:


Could you please post a little more on this - i'm not sure i fully understand it, but it sounds very interesting.

Note: I need to see the some member functions, as well as some operators.

Thenk you.
A better solution than using an anonymous union was posted a while back. Search for "A slick trick in C++".
Unless you have severe memory constraints It would be way easier to just use a vec4 all the time and if you don’t need the extra parameters just set them to 0

This topic is closed to new replies.

Advertisement