5

I want to write a class that manages euclidean vector and that store its initial point using short, int, long or float. I thought to create a template like this:

    template<class unit> class EVector
{
private:
    unit x;
    unit y;
public:
    EVector();
    setX();
    setY();
};

So user creates an EVector choosing the suitable primitive type. But how can I implement the operation between different classes, e.g.

EVector<int> a;
EVector<float> b;

EVector<double> c;

c = a + b;  

operator= will copy the coordinates, operator+ adds them.

Clynamen
  • 509
  • 1
  • 6
  • 16

2 Answers2

3

For addition, you can use my promote implementation:

template<typename A, typename B> 
EVector<typename promote<A, B>::type>
operator +(EVector<A> const& a, EVector<B> const& b) {
  EVector<typename promote<A, B>::type> ev;
  ev.setX(a.getX() + b.getX());
  ev.setY(a.getY() + b.getY());
  return ev;
}

For types double and int, it will yield double for example.

Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • So this solution won't take into account all conversions, only promotions. Not sure if this is what the OP wants. I like the promote implementation, though, so, here's +1 from me ;) – Armen Tsirunyan Jul 17 '11 at 14:11
  • @Armen all conversions that `?:` does, which comes down to all conversions if I'm not mistaken :) For example `char*` and `std::string` will work too, even though that's not a promotion of any kind. The name `promote` could perhaps be renamed. Thanks for your +1 :) – Johannes Schaub - litb Jul 17 '11 at 14:12
  • If it'll work for all conversions, what's the need of such scary code when a simple templated copy-constructor and copy-assignment would do? – Armen Tsirunyan Jul 17 '11 at 14:13
  • @Armen I would be eager to know how you would write `operator+` with templated constructors :) – Johannes Schaub - litb Jul 17 '11 at 14:14
  • I'd just write a simple operator + and one of the operands would get converted to the other one via the constructor. – Armen Tsirunyan Jul 17 '11 at 14:18
  • @Armen which one will be converted to which other one? Should `a + b` yield `1` if `a` is `int 1` and `b` is `float 0.3`, because you always convert to the left operand? – Johannes Schaub - litb Jul 17 '11 at 14:21
  • @Johannes It's hard for me to fully understand your implementation, but I think this is the right solution. Thank you – Clynamen Jul 17 '11 at 16:23
2

You want to enable assignment(and copy-construction) from EVector<U> to EVector<T> when Uis convertible to T

template<class T>
class EVector
{
   template<class U>
   EVector(EVector<U> const & rhs)
           :x(rhs.x), y(rhs.y)
   {
   }
   ...
}

Note that even if you have provided this templated copy-constructor, the compiler will generate a copy-constructor for you( when T is same as U). In this case you're fine with that default implementation - it does exactly what you need. But otherwise you'd have to explicitly define the nontemplated constructor(and copy-assignment) as well.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • "Note that once you have provided this templated copy-constructor, you'll have to explicitly provide a nontemplated one as well", this is not true :) – Johannes Schaub - litb Jul 17 '11 at 14:00
  • @Johannes: Oh, OK, I got it... I'll think how to edit now... :) – Armen Tsirunyan Jul 17 '11 at 14:07
  • I like it more but I'm not sure what you mean by "But otherwise". In what cases would an explicitly defined nontemplated copy constructor be needed? I can't understand. – Johannes Schaub - litb Jul 17 '11 at 14:24
  • @Johannes: When you're not happy with the compiler generated copy constructor. My point is that providing a templated "copy-"constructor will not prevent the compiler from generating a real copy-constructor - and that badly generated one will be called when you initialize `EVector` from `EVector` - not the instantiation of the template with `U = T` – Armen Tsirunyan Jul 17 '11 at 14:43