I am new to Delphi. For the project required by my company, I need to translate the code from our existing C ++ classes to Delphi. Some of these classes are templates, such as:
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; }
I use it, for example. with this code
APoint<float> pt; pt.m_X = 2.0f; pt.m_Y = 4.0f; pt.Add(5.0f);
and it works well.
Now I need to write equivalent code for Delphi. I tried to write a Delphi Generic class based on the C ++ code above:
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;
However, this code does not compile. I get this error:
E2015 Operator not applicable to this type of operand
AFAIK, this code should work, and I donโt understand what is wrong with it. So can someone explain to me:
Why doesnโt such code compile in Delphi?
What is the correct (and easiest) way in Delphi to create a template class that provides the Add() function as close as possible to the C ++ code and usage above?
EDITED 10/17/2016
Thanks for all the answers. Therefore, if I understood correctly, there is no way to create a style template similar to C ++, because Delphi imposes several restrictions that do not exist in C ++.
Based on this, I was looking for a workaround to achieve the goal I want. I found the following solution:
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;
I use it, for example. with this code
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;
and it works well. However, I find the style a bit heavy, for example. the need to use APointF (pt). So, regarding the above code, my questions are:
- Is this a good solution? (that is, it is better to write a version of each entry for each type that I want to support, for example, APointF, APointI, APointD, ...)
- Is there any way to simplify this code, for example. solution to call pt.m_X directly without converting APointF (pt)? ( NOTE Here I omitted the implementation of properties, even if I find them more elegant than direct access to a variable)
- How about the speeches of this decision? (Ie this solution is much slower than directly adding the value m_X: = m_X +?)
Finally, I saw another solution in Delphi code, where you can implement a comparison of the equalities of two types of a general form as follows:
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;
I tried to read the code behind the scene, however I found it terribly complicated. So my questions are:
- Is such a solution better than the one suggested above?
- Is there a similar ready-to-use solution for mathematical operations?
- How acceptable is the implementation of such a decision?
thank you for your responses
Hello