template function w/ type & non-type parameters

I have the following class definitions:

template<unsigned dim>
class Vector
{ ... };

template<unsigned dim>
class Displacement : public Vector<dim>
{ ... };
template<unsigned dim>
class Velocity : public Vector<dim>
{ ... };
template<unsigned dim>
class Acceleration : public Vector<dim>
{ ... };

etc.

Now I want to overload binary operators +, - , *, /. But I don't want to write member functions for all vector types. (there are too many.) So I wrote the following template function:
      template<typename T, unsigned dim>
      T<dim> operator + (const T<dim> & t0, const T<dim> & t1)                 <<<< C2988 on this line
      {
            T<dim> ret;
            for (int i=0; i<dim; i++)
                  ret[i] = t0[i] + t1[i];
      }
But I get compiler error C2988 (unrecognizable template declaration/definition; Visual Studio Pro 2008). The help page (http://msdn.microsoft.com/en-us/library/f69a8fb8.aspx) is pretty useless.
Is it possible to write template like above (of course, w/o syntax errors) or do I have no choice but to copy-paste for all types derived from Vector<dim>?
LVL 9
jhshuklaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
Hmmm, I guess you meant the following:
      template<typename T, unsigned dim>
      T operator + (const T & t0[dim], const T & t1[dim])
      {
            T ret[dim];
            for (int i=0; i<dim; i++)
                  ret[i] = t0[i] + t1[i];
      }

Open in new window

0
jhshuklaAuthor Commented:
no I did not mean that.
The code you suggested would create (well, it is reference. so technically not "create" but let me use that term here anyways) an array of T's. I want one variable of type T<dim>.

and if [] inside the function confused you, it is using overloaded [] operator. to be more elaborate this is how Vector class is defined:
	template<unsigned dim>
	class Vector
	{
	public:
		Vector(double *init = NULL)
		{
			if (init == NULL)
				memset(components, 0, sizeof(components));
			else
				memcpy(components, init, sizeof(components));
		}
		~Vector(void) {}
 
		inline double operator[](int i) const { return components[i]; }
		inline double & operator[](int i) { return components[i]; }
 
/*
		these commented out functions are the ones I want to mimic using
		templates
		inline Vector<dim> operator/(double div) const
		{
			Vector<dim> ret;
			for (int i=0; i<dim; i++)
				ret[i] = components[i] / div;
		}
		inline Vector<dim> operator*(double mul) const
		{
			Vector<dim> ret;
			for (int i=0; i<dim; i++)
				ret[i] = components[i] * mul;
		}
 
		inline Vector<dim> operator+(Vector<dim> that) const
		{
			Vector<dim> ret;
			for (int i=0; i<dim; i++)
				ret[i] = components[i] + that[i];
		}
		inline Vector<dim> operator-(Vector<dim> that) const
		{
			Vector<dim> ret;
			for (int i=0; i<dim; i++)
				ret[i] = components[i] - that[i];
		}
*/
		inline double MagnitudeSq() const
		{ return dot(*this, *this); }
		inline double Magnitude() const
		{ return sqrt(MagnitudeSq()); }
		inline static double dot(const Vector<dim> & v0, const Vector<dim> & v1)
		{
			double accum = 0;
			for (int i=0; i<dim; i++)
				accum += v0[i]*v1[i];
			return accum;
		}
 
	private:
		double components[dim];
	};

Open in new window

0
jhshuklaAuthor Commented:
Forgot to mention that T will always be a derived class of Vector<dim>.

I expect to be able to use the template like this:
Displacement<3> d1, d2, d3;
d3 = d1 + d2;

The addition statement will cause the following function to be instantiated:
Displacement<3> operator + (const Displacement<3> &t0, const Displacement<3> &t1)
{ ... }

I found something called "template template parameter." no, it is not a typo. the word "template" is repeated. but cannot get it to work. e.g.
http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/topic/com.ibm.vacpp6m.doc/language/ref/clrc16template_template_parameters.htm
and with some explanation: http://www.informit.com/articles/article.aspx?p=376878

I modified the function template after reading InformIT article but I get even more errors now:
      template<template<unsigned dim> T>
      T operator + (const T & t0, const T & t1)
      {
            T ret;
            for (int i=0; i<dim; i++)
                  ret[i] = t0[i] + t1[i];
      }
0
jhshuklaAuthor Commented:
update. I made a mistake above. it is supposed to be the following:
      template<template<unsigned dim> class T>
      T operator + (const T & t0, const T & t1)                   <<< C3205 here
      {
            T ret;
            for (int i=0; i<dim; i++)
                  ret[i] = t0[i] + t1[i];
      }

however, now I am getting the error: "C3205: argument list for template template parameter 'T' is missing."
If I replace it with T<dim> it says "error C2065: 'dim' : undeclared identifier."
      template<template<unsigned dim> class T>
      T<dim> operator + (const T<dim> & t0, const T<dim> & t1)
      {
            T<dim> ret;
            for (int i=0; i<dim; i++)
                  ret[i] = t0[i] + t1[i];
      }
0
jhshuklaAuthor Commented:
phew. finally figured it out.

found clue here: http://hal.iwr.uni-heidelberg.de/lehre/prosem-06/Popov.pdf
scroll to p11

// This works:
	template<template<unsigned> class T, unsigned dim>
	T<dim> operator + (const T<dim> & t0, const T<dim> & t1)
	{
		T<dim> ret;
		for (int i=0; i<dim; i++)
			ret[i] = t0[i] + t1[i];
		return ret;
	}
 
// This should work too (template parameters are switched. nothing big):
	template<unsigned dim, template<unsigned> class T>
	T<dim> operator + (const T<dim> & t0, const T<dim> & t1)
	{
		T<dim> ret;
		for (int i=0; i<dim; i++)
			ret[i] = t0[i] + t1[i];
		return ret;
	}
 
// after this we can use statements like:
Displacement<3> d1, d2, d3;
d3 = d1 + d2;
Velocity<2> v1, v2, v3;
v1 = v2 + v3;

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.