【问题标题】:Overriding multiplication operator for different datatypes覆盖不同数据类型的乘法运算符
【发布时间】:2022-01-18 04:33:21
【问题描述】:

我创建了以下类

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>&);

我想覆盖不同数据类型的乘法函数,例如 int 和 double 这样的

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;
}

我在 Polar 中将函数声明为好友,如下所示:

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

然后实现如下:

 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)};  
 }

但由于在扣除前使用自动,我得到了一个错误。 我不知道如何让返回类型起作用,我不想为每个可能的组合编写一个函数。

有没有简单的方法来解决这个问题?

【问题讨论】:

  • 你有没有问过自己operator*的返回类型应该是什么?
  • 它应该返回一个带有乘法结果的新 Polar 类。但是在必要时使用类型转换,例如 int * double 应该返回一个 double 但 int * int 应该只返回 int
  • 你试过用Polar&lt;decltype(A * C),decltype(C + D)&gt;替换auto吗?
  • 是的,但它只会导致很多错误(token * 之前的预期主表达式)
  • 您可能想在此处使用common_type_t,以确定输出类型。

标签: c++ templates operator-overloading


【解决方案1】:

好的,我知道了,我只需要更改类中的声明

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

致以下:

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)>;

【讨论】:

【解决方案2】:

使用std::common_type_t&gt; 可以在这里服务。它给你"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;
}

【讨论】:

  • 注意:像往常一样,对于小于int 的整数类型,std::common_type_t&lt;A, A&gt;Adecltype(A() * A())int
  • @Jarod42 谢谢!这将使decltype(A() * A()) 成为避免可能溢出的更好选择,不是吗?
  • 只适用于小于int的类型,所以一般情况下不适用。
猜你喜欢
  • 2016-09-06
  • 2011-05-31
  • 2019-03-13
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
  • 1970-01-01
  • 2013-06-12
相关资源
最近更新 更多