Home > Net >  Overriding multiplication operator for different datatypes
Overriding multiplication operator for different datatypes

Time:12-15

I created the following class

template<typename T, typename S>
class Polar{

private:
  T rad;
  S phi;

public:
  Polar(T r, S p) : rad{r}, phi{p} {}
  template<typename A, typename B> 
  friend std::ostream& operator<<(std::ostream&, const Polar<A,B>&);

And i want to override the multiplication function for different datatypes for example int and double like this

int main() {
   Polar<int,int> p{2,3};
   Polar<int,int> w{4,5};
   Polar<float,double> z{6,7};

   std::cout << p*w << std::endl;
   std::cout << p*z << std::endl;
  return 0;
}

I declared the function as a friend in Polar like this:

 template<typename A, typename B, typename C, typename D> 
 friend auto operator*(const Polar<A,B>&, const Polar<C,D>&);

And then implemented it as the following:

 template<typename A, typename B, typename C, typename D>
 auto operator*(const Polar<A,B>& p, const Polar<C,D>& w) -> Polar<decltype(p.rad * w.rad),decltype(p.phi   w.phi)>
 {
   return Polar<decltype(p.rad * w.rad),decltype(p.phi   w.phi)> {(p.rad * w.rad),(p.phi   w.phi)};  
 }

But i am getting an error because of using auto before deduction. I dont know how to get the return-type to work and i dont want to write a function for each possible combination.

Is there an easy way to tackle this?

CodePudding user response:

Okay i got it i only needed to change the declartion in class from

 template<typename A, typename B, typename C, typename D> 
 friend auto operator*(const Polar<A,B>&, const Polar<C,D>&);

To the following:

template<typename A, typename B, typename C, typename D> 
friend auto operator*(const Polar<A,B>& p, const Polar<C,D>& w) -> Polar<decltype(p.rad * w.rad),decltype(p.phi   w.phi)>;

CodePudding user response:

Using std::common_type_t> may serve here. It gives you "the common type among all types T..., that is the type all T... can be implicitly converted to."

[Demo]

#include <iostream>  // cout
#include <ostream>
#include <type_traits>  // common_type_t

template<typename T, typename S>
class Polar
{
public:
    Polar(T r, S p) : rad{r}, phi{p} {}

    template<typename A, typename B> 
    friend std::ostream& operator<<(std::ostream&, const Polar<A, B>&);
    
    template<typename A, typename B, typename C, typename D>
    friend auto operator*(const Polar<A, B>& p, const Polar<C, D>& w);
private:
    T rad;
    S phi;
};

template<typename A, typename B> 
std::ostream& operator<<(std::ostream& os, const Polar<A, B>& p)
{
    return os << "(" << p.rad << ", " << p.phi << ")";
}

template<typename A, typename B, typename C, typename D>
auto operator*(const Polar<A, B>& p, const Polar<C, D>& w)
{
    using RT = std::common_type_t<A, C>;
    using RS = std::common_type_t<B, D>;
    
    return Polar<RT, RS>{p.rad * w.rad, p.phi   w.phi};
}

int main()
{
   Polar<int, int> p{2, 3};
   Polar<int, int> w{4, 5};
   Polar<float, double> z{6.5, 7.5};

   std::cout << p* w << std::endl;
   std::cout << p*z << std::endl;
}
  • Related