模板类实例接收不同类型的相同模板类的另一个实例

template class instance receiving another instance of the same template class of different type

本文关键字:实例 另一个 同类型      更新时间:2023-10-16

模板类实例如何接收不同类型的相同模板类的另一个实例作为其某些函数成员的参数?(我很难用更简单的方式表达我的问题,对此我感到非常抱歉。

这是一个工作代码。我创建了一个类,并将其命名为 MyClass。它在其运算符=和运算符+成员函数上接受相同类型(为int)的相同模板类。

#include <iostream>
using namespace std;
template<class T>
class MyClass {
protected:
  T __val;
public:
  MyClass();
  MyClass(T val): __val(val) {}
  void operator= (const MyClass<T>& r)
  {
    __val = (T)r.__val;
  }
  const MyClass<T>& operator+ (const MyClass<T>& r)
  {
    return *(new MyClass<T>(__val + (T)r.__val));
  }
  T retval() {return __val;}
};
int main()
{
  MyClass<int> myclass1(1);
  MyClass<int> myclass2(2);
  MyClass<int> myclass3 = myclass1 + myclass2;
  cout << myclass3.retval() << endl;
  return 0;
}

出于以下目的,我__val运算符=和运算符+的参数成员进行了类型转换:

int main()
{
  MyClass<int> myclass1(1);
  MyClass<double> myclass2(2.5);
  MyClass<int> myclass3 = myclass1 + myclass2;
  cout << myclass3.retval() << endl;
  return 0;
}

显然我会得到一个错误。我不能仅仅MyClass<int>::operator+因为 myclass2 想要MyClass<int>参数而不是MyClass<double>而将 myclass2 作为参数传递给 myclass1 的运算符 + 。我知道我可以重载另一个接受MyClass<double>运算符+,但我也想用其他数字类型(如浮点数、单数等)来重载。为所有这些函数制作重载函数会使我的代码更大,这显然不希望发生。

我必须从 MyClass 更改什么才能使我的第二个主函数正常工作?

您需要一个模板成员operator+。此外,它应该返回一个值,而不是一个引用:

template<class T>
class MyClass 
{
 public:
  template <typename T2>
  MyClass operator+ (const MyClass<T2>& r) const { return _val + r.retval(); }
  T retval() const {return _val;}
  // as before
};

请注意,这将在涉及 operator+ 的表达式中返回与 LHS 类型相同的值。请注意,最好将operator+实现为非成员二进制运算符。但是你必须实现一些编译时逻辑来确定返回类型:

template <typename T1, typename T2>
MyClass< ?? > operator+(const MyClass<T1>& lhs, const MyClass<T1>& rhs)
{
  return lhs.retval() + rhs.retval();
}

其中??应替换为编译构造,以根据T1T2选择类型。据推测,这将是这两种类型之一。这是一个 C++11 示例:

template <typename T1, typename T2>
auto operator+(const MyClass<T1>& lhs, const MyClass<T1>& rhs)->decltype(lhs.retval()+rhs.retval())
{
  return lhs.retval() + rhs.retval();
}

这样做的好处是,返回类型是独立于 LHS 或 RHS 上的内容确定的。

你可以

这样写:

template<typename _Ty> MyClass<T> operator+ (const MyClass<_Ty>& r) {
   return MyClass<T>(__val + (static_cast<_Ty> (r.__val)) );
}

以提供成员函数。但要更普遍地支持它,请像:

template<typename _T,typename _Ty> MyClass<_T> operator+ (const Myclass<_T>& p,const MyClass<_Ty>& r) {
       return MyClass<T>(p.__val + (static_cast<_T> (r.__val)) );
    }

不幸的是,为此您必须将__val清除为公共

强制转换比点具有更强的优先级,即代替

(T)r.__val

你必须写

(T) (r.__val)

更好的是,使用static_cast.因此,定义operator +类似

template<class S>
MyClass<T> operator+ (const MyClass<S>& r) {
   return MyClass<T>(__val + (static_cast<S> (r.__val)) );
}

或者根本不使用显式强制转换:

template<class S>
MyClass<T> operator+ (const MyClass<S>& r) {
   return MyClass<T>(__val + r.__val);
}
最好

让 retval 返回一个 const T &,在运算符 + 的实现中使用 retval (),并使运算符 + 成为非成员非友元:

template<class T>
class MyClass {
private:
  T m_val;
public:
  MyClass(T val): m_val(val) {}
  const T & retval () const {return m_val;}
};
template<class T1, class T2>
auto operator+ (const MyClass<T1>& r1, const MyClass<T2> & r2)
-> MyClass < std::remove_const < std::remove_reference <
   decltype ( r1.retval () + r2.retval () ) 
> > > {
    return r1.retval () + r2.retval ();
}