操作符重载和不同的模板参数

Operator overloading and different template parameter

本文关键字:参数 重载 操作符      更新时间:2023-10-16

在模板化类中重载操作符+有问题。假设我有

template<typename T>
struct point{
    //Ctors:
    point(){};
    point(T _x, T _y):x(_x),y(_y){};
    point(const point<T>& p):x(p.x),y(p.y){};
    template<typename T2>
    point(const point<T2>& p):x(static_cast<T>(p.x)),y(static_cast<T>(p.y)){};

   //Coordinates:
   T x;
   T y;

   //Operator overloads:
   friend point<T> operator+(point<T> left,point<T> right ){
       return point<T>(left.x+right.x, left.y+right.y);
   }
   template<class T2>
   friend point<T> operator+(point<T2> left,point<T> right){
       return point<T>(left)+right;
   }
   template<class T3>
   friend point<T> operator+(point<T> left,point<T3> right){
       return point<T>(right)+left;
   }

};

在调用。

时会产生歧义错误。
point<float> p1(1.2,1.4);
point<int> p2(1,2);    
point<float> p3 =p1+p2;    

这很有意义,但是你能告诉我如何解决这个问题吗?

我需要3个操作符,否则转换可能会走向错误的方向。例如,忽略最后一个操作符重载将导致p3.x=2p3.y=4

非常感谢!

在某种程度上,这是个人偏好和主观意见的问题,但我认为我会尝试模仿普通的c++规则来处理算术表达式的结果类型,例如

template <class T1, class T2 >
friend
auto operator+( Point<T1> const left, Point<T2> const right )
    -> Point< decltype( left.x + right.x ) > 
{
    return {left.x + right.x, left.y + right.y};
}

同时满足g++ 4.8.2和visualc++ 12.0的要求比我想象的要复杂得多,但下面的具体代码可以在这两个编译器中清晰地编译:

#include <type_traits>
#include <utility>
template< class Number >
struct Point
{
    Number  x;
    Number  y;
};
template< class T1, class T2 >
auto operator+( Point<T1> const left, Point<T2> const right )
    -> Point< typename std::remove_const<decltype( left.x + right.x )>::type > 
{
    using Result_number =
        typename std::remove_const<decltype( left.x + right.x )>::type;
    using Result_point = Point< Result_number >;
    return Result_point{ left.x + right.x, left.y + right.y };
}
auto main()
    -> int
{
    Point<float> const  p1{ 1.2, 1.4 };
    Point<int> const    p2{ 1, 2 };
    Point<float> const  p3 = p1 + p2;
}

为了方便Point的可能的窄化转换,可以添加一个显式的转换操作符成员函数,如下所示:

template< class Number >
struct Point
{
    Number  x;
    Number  y;
    template< class Other_number >
    explicit
    operator Point<Other_number>() const
    {
        return Point<Other_number>{
            static_cast<Other_number>( x ),
            static_cast<Other_number>( y )
            };
    }
};

调用使用任何合适的强制转换,例如明显的构造函数表示法(上面的定义只是调用转换操作符的强制转换):

    Point<int> const    p4 = Point<int>( p1 + p2 );

如果您想在result参数的类型中使用result,则创建计算它的方法:

   template<class T, class T2, class T3>
   void AddPoints(const point<T>& a, const point<T2>& b, point<T3>& result)
   {
       result = point<T3>(a) + point<T3>(b);
   }
int main()
{
    point<float> p1(1.2,1.4);
    point<int> p2(1,2);    
    point<double> result; 
    AddPoints(p1, p2, result);
}