Перегрузка оператора и другой параметр шаблона

У меня проблема с перегрузкой оператора + шаблонный класс.
Предположим, у меня есть

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=2 а также p3.y=4,

Большое спасибо!

1

Решение

В некоторой степени это вопрос личных предпочтений и субъективного мнения, но я думаю, что я попытался бы подражать обычным правилам 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, так и visual c ++ 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 );
4

Другие решения

Если вы хотите иметь результат в типе параметра результата, то создайте метод для его вычисления:

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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector