   unknown return types with templates
  I attempted to create a 3 dimensional vector class using templates and overloaded operators, but I ran into a problem. I can't figure out what to put as the return types.The class I was trying to create as three operations: Adding vectors, taking the dot product of vectors, and multiplying a vector by a scalar. The problem is that it seems like it is impossible to know what the return types are because they depend on what T is.How can I do this correctly?template <class T>class V3{    T x,y,z;    public:    //constructor not shown    //vector addition ? operator + (V3<T> other) const    {   return V3<?>(x+other.x, y + other.y, z+other.z);    }    //dot product    ? operator * (V3<T> other) const    {   return (x * other.x + y * other.y + z * other.z);    }    //scalar multiplication    ? operator * (T scalar) const    {   return V3<?>(x * scalar, y * scalar, z * scalar);    }};
  Adding two vectors produces a vector, so the return type would be V3<T> The dot product produces a scalar, so the return type would be T.The template parameter (if it is a type parameter) is a type, so you may use it where a type would be appropriate -- just as you did in the declaration of your member variables.;  Wouldn't you just return type T?[Edit: NINJA'D!]   ;  Perhaps it's clearer if you use namespace-level binary operators.template <class T>  class V3  {    T x,y,z;   public:    //vector addition V3& operator+=(V3<T> other)    {   x += other.x; y += other.y, z += other.z;   return *this;    }    // ...  };template <class T>  V3<T> operator+(const V3<T>& lhs, const V3<T>& rhs)  {    V3<T> tmp(lhs);    return tmp += rhs;  };  While we're at it, I've read that the following form of the above is better for optimization in some cases, though perhaps more recent compilers will generate the same code, regardless.//...template <class T>  V3<T> operator+(V3<T> lhs, const V3<T>& rhs) // lhs no longer const reference  {    return lhs += rhs;  }I forget which book, exactly, I had read this in, but I'm sure it was from Scott Meyer or another equally respectable author.   ;Quote:Original post by RavyneWhile we're at it, I've read that the following form of the above is better for optimization in some cases, though perhaps more recent compilers will generate the same code, regardless.They better not generate the same code.  They have different functionality.  I can pretty much guarantee it's better for optimization but then again it's not doing the same thing.It reminds me of FORTRAN where you could alter the value of a constant like '0' if you modified parameters.  Man, those were hard bugs to track down.   ;Quote:Original post by BTownTKDWouldn't you just return type T?[Edit: NINJA'D!]That works if T is a primitive, but what if T is a class that has it's own overloaded * operator?For example suppose T was V3<int>V3<V3<int>> * V3<int> should return a V3<int>, not a V3<V3<int>>   ;Quote:Original post by StoryyellerFor example suppose T was V3<int>V3<V3<int>> * V3<int> should return a V3<int>, not a V3<V3<int>>Excuse my ignorance, but why do you want different functionality for different types?If I were using a vector class I would assumeV3<int>(1,1,1) * 5 would return V3<int>(5,5,5)Likewise I would assumeV3<V3<int>>(V3<int>(1,2,1) ... * V3<int>(5 ... would return V3<V3<int>>(V3<int>(5,10,5) ...I am confused as to why it should return anything else   ;  Because scalar multiplication multiplies every element in the LHS by the entire RHSIn the case of V3<V3<int>>, V3<int> is a scalarHere's an exampleFor the sake of clarity, I'm just going to write vectors as {x,y,z}Consider {{1,2,1},{3,2,1},{0,-2,-2}} * {5,3,2}Each element of the first vector is multiplied by {5,3,2} so{{1,2,1},{3,2,1},{0,-2,-2}} * {5,3,2}= {{1,2,1} * {5,3,2}, {3,2,1} * {5,3,2}, {0,-2,-2} * {5,3,2}}Now, each element is a V3<int> times a V3<int> so it's the dot product{{1,2,1} * {5,3,2}, {3,2,1} * {5,3,2}, {0,-2,-2} * {5,3,2}}= {1 * 5 + 2 * 3 + 1 * 2, 3 * 5 + 2 * 3 + 1 * 2, 0 * 5 + -2 * 3 + -2 * 2}since, these are all ints, the + and * operate normally and this turns into{1 * 5 + 2 * 3 + 1 * 2, 3 * 5 + 2 * 3 + 1 * 2, 0 * 5 + -2 * 3 + -2 * 2}={ 13 , 23, -10 }So the result of multiplying a V3<V3<int>> by a V3<int> is another V3<int>At least that's the intuitive way it should behave.The problem is not wanting different functionality for each type, but wanting the same functionality. I'm beginning to think this is impossible.   ;  I would go with separate, explicit, operators, like I explained here.   