Точная ситуация следующая:
Я определил в системных API-структурах CGPoint и CGSize, и я хочу иметь возможность писать my_point = my_size.
Я не могу изменить структуру CGPoint, но может писать внешний оператор. Я могу написать двоичные операторы (+, -,...), но operator= должен быть объявлен внутри структуры. Итак, есть ли другое решение?
Можно ли написать оператор автозапуска вне структуры?
Ответ 1
Чтобы скомпилировать выражение a = b;, вам нужно либо иметь operator= в типе a, который принимает элемент типа b, либо тип, неявно конвертируемый из b.
Первый случай исключается, так как operator= должен быть членом класса, и поскольку вы не можете изменить GLPoint, вы не можете добавить GLPoint& GLPoint::operator=( GLSize ).
Второй случай страдает от того же типа проблем. Неявное преобразование из GLSize в GLPoint может быть реализовано как неявный конструктор в GLPoint (исключен) или как член operator GLPoint() в GLSize, что требует модификации GLSize. Конверсии также не могут быть добавлены как свободные функции.
Альтернативы используют синтаксис без оператора, добавляя свободную функцию assign (или copy): GLPoint& assign( GLPoint&, GLSize const & ).
Следующий вопрос - почему вы хотите это сделать. Если дизайнеры GLPoint и GLSize не считали, что размер должен быть назначен для точки, то почему вы чувствуете, что они должны быть назначаемыми? В общем, рекомендуется сохранять типы отдельно, поскольку это позволит компилятору обнаруживать ошибки, которые могут возникнуть в вашем коде.
Если вы разрешаете неявные преобразования от GLSize до GLPoint, вы можете по ошибке ввести что-то вроде: distance( point1, size2 ), где вы имели в виду distance( point1, point2 ), а поскольку есть преобразование, компилятор с радостью будет конвертировать и применять. Затем вы увидите странные результаты, и вы проведете немало приятных отладочных часов, пытаясь определить, где логика неправильная.
Если у домена нет четкого определения того, что означает каждый оператор в этом контексте, я бы избегал перегрузки оператора любой ценой. Будут ли все, кто читает ваш код, сразу понять, что GLPoint(1,2) + GLSize(5) представляет без сомнения или двусмысленности? Если это не так, если люди будут удивлены или даже сомневаются, то избегайте перегрузки оператора и используйте именованные функции: move_up( GLPoint&, GLSize ) (или любой другой размер + размер означает для вас)
Ответ 2
Когда вы назначаете CGSize в CGPoint - что происходит? Переопределите это на некоторый оператор и там у вас есть - например
CGPoint& operator|=(CGPoint& cPoint, CGSize const& cSize)
{
// now set attributes of cPoint that you can extract from cSize
return cPoint;
}
Что так сложно? Вот пример: http://www.ideone.com/FZN20
Ответ 3
Если вы можете получить или обернуть CGPoint и использовать новый класс вместо всего кода, то вы можете предоставить любые операторы, которые вам нравятся. Новый класс может иметь оператор преобразования CGPoint, способствующий взаимодействию с существующими функциями.
Ответ 4
Другие ответы швы, чтобы пропустить очевидное решение: добавьте функцию для преобразования CGPoint в CGSize. Конечно, это не совсем то, что вы хотите (size = point), но поскольку вы не можете изменить один из двух классов, это единственный способ:
CGSize ToSize( const CGPoint &pt )
{
CGSize res = ...
// do the conversion
return res;
}