Я новичок в Delphi. Для проекта, требуемого моей компанией, мне нужно перевести код из наших существующих классов C ++ в Delphi. Некоторые из этих классов являются шаблонами, такими как:
template <class T>
struct APoint
{
T m_X;
T m_Y;
virtual void Add(T value);
};
template <class T>
void APoint<T>::Add(T value)
{
m_X += value;
m_Y += value;
}
Я использую его, например, с помощью этого кода
APoint<float> pt;
pt.m_X = 2.0f;
pt.m_Y = 4.0f;
pt.Add(5.0f);
и это хорошо работает.
Теперь мне нужно написать эквивалентный код для Delphi. Я попытался написать класс Delphi Generic, основанный на коде C ++ выше:
APoint<T> = record
m_X: T;
m_Y: T;
procedure Add(value: T);
end;
procedure APoint<T>.Add(value: T);
begin
m_X := m_X + value;
m_Y := m_Y + value;
end;
Однако этот код не компилируется. Я получаю эту ошибку:
E2015 Оператор не применим к этому типу операнда
AFAIK этот код должен работать, и я не понимаю, что с ним не так. Так может кто-нибудь объяснить мне:
-
Почему такой код не компилируется в Delphi?
-
Каков правильный (и самый простой) способ в Delphi создать класс шаблона, который обеспечивает Add()
функцию, максимально приближенную к коду C ++ и использованию выше?
EDITED 17.10.2016
Спасибо за все отклики. Поэтому, если я правильно понял, нет способа создать шаблон стиля, подобный c ++, потому что Delphi накладывает несколько ограничений, которые не существуют в c ++.
Исходя из этого, я искал обходной путь, чтобы достичь цели, которую я хочу. Я нашел следующее решение:
IPoint<T> = interface
procedure Add(value: T);
end;
APoint<T> = class(TInterfacedObject, IPoint<T>)
m_X: T;
m_Y: T;
procedure Add(value: T); virtual; abstract;
end;
APointF = class(APoint<Single>)
destructor Destroy; override;
procedure Add(value: Single); reintroduce;
end;
destructor APointF.Destroy;
begin
inherited Destroy;
end;
procedure APointF.Add(value: Single);
begin
m_X := m_X + value;
m_Y := m_Y + value;
end;
Я использую его, например, с помощью этого кода
procedure AddPoint;
var
pt: IPoint<Single>;
begin
pt := APointF.Create;
APointF(pt).m_X := 2.0;
APointF(pt).m_Y := 4.0;
APointF(pt).Add(5.0);
end;
и это хорошо работает. Однако я считаю, что стиль немного тяжелый, например, необходимость использовать APointF (pt). Итак, в связи с вышеприведенным кодом, мои вопросы:
- Является ли это решение хорошим решением? (то есть лучше написать версию каждой записи для каждого типа, который я хочу поддерживать, например, APointF, APointI, APointD, ...)
- Есть ли способ упростить этот код, например, решение для вызова pt.m_X напрямую без преобразования APointF (pt)? ( ПРИМЕЧАНИЕ. Здесь я опустил реализацию свойств, даже если я считаю их более элегантными, чем прямой доступ к переменной)
- Как насчет выступлений этого решения? (Т.е. это решение значительно медленнее, чем прямое добавление значения m_X: = m_X +?)
Наконец, я увидел другое решение в коде Delphi, где можно реализовать сравнение равенства двух типов общего вида следующим образом:
function APoint<T>.IsEqual(const other: APoint<T>): Boolean;
var
comparer: IEqualityComparer<T>;
begin
Result := (comparer.Equals(m_X, other.m_X) and comparer.Equals(m_Y, other.m_Y));
end;
Я попытался прочитать код за сценой, однако я нашел это ужасно сложным. Итак, мои вопросы:
- Является ли такое решение лучше, чем предлагаемое выше?
- Есть ли аналогичное готовое решение для математических операций?
- Являются ли результаты такого решения приемлемыми?
Заранее благодарю за ваши ответы
С уважением