Ich bin neu in Delphi. Für ein Projekt, das von meiner Firma benötigt wird, muss ich Code aus unseren bestehenden C++ - Klassen nach Delphi übersetzen. Einige dieser Klassen sind Templates, wie zum Beispiel:Arithmetische Operationen mit generischen Typen in Delphi
Ich benutze es z.B. mit diesem Code
APoint<float> pt;
pt.m_X = 2.0f;
pt.m_Y = 4.0f;
pt.Add(5.0f);
und das funktioniert gut.
Jetzt muss ich gleichwertigen Code für Delphi schreiben. Ich habe versucht, eine Delphi generische Klasse zu schreiben, basierend auf dem C++ Code oben:
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;
jedoch dieser Code nicht kompiliert. Ich bekomme diesen Fehler:
AFAIK dieser Code sollte funktionieren, und ich verstehe nicht, was ist falsch mit ihm. So kann mir jemand erklären:
Warum ein solcher Code in Delphi nicht kompiliert?
Was ist der korrekte (und einfachste) Weg in Delphi, um eine Template-Klasse zu erstellen, die eine
Add()
-Funktion bietet, die dem C++ - Code und der obigen Verwendung am nächsten kommt?
auf 2016.10.17
EDITEDDanke für alle Antworten. Wenn ich also richtig verstanden habe, gibt es keine Möglichkeit, eine C++ - ähnliche Stilvorlage zu erstellen, da Delphi mehrere Einschränkungen auferlegt, die in C++ nicht existieren.
Darauf basierend suchte ich einen Workaround, um das gewünschte Ziel zu erreichen. Ich fand die folgende Lösung:
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;
Ich benutze es zum Beispiel mit diesem 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;
und das funktioniert gut. Jedoch finde ich den Stil etwas schwer, z.B. die Notwendigkeit, APointF (pt) zu verwenden. In Bezug auf obigen Code sind meine Fragen also:
- Ist diese Lösung eine gute Lösung? (d. h. besser, eine Version jedes Datensatzes für jeden Typ zu schreiben, den ich unterstützen möchte, wie z. B. APointF, APointI, APointD, ...)
- Gibt es eine Möglichkeit, diesen Code zu vereinfachen, z. eine Lösung um pt.m_X direkt ohne die APointF (pt) Konvertierung aufzurufen? (NOTE Ich habe hier die Implementierung von Eigenschaften weggelassen, auch wenn ich denke, sie eleganter als der Zugriff auf die Variable direkt)
- Was ist mit den Leistungen dieser Lösung? (Ie ist diese Lösung drastisch langsamer als eine direkte m_X: = m_X + Wert Addition? )
Schließlich sah ich eine andere Lösung in dem Delphi-Code, wo es möglich ist, einen Gleichheitsvergleich von 2 generischen Typen auf diese Weise zu implementieren:
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;
Ich habe versucht, den Code hinter der Szene zu lesen aber ich fand es furchtbar kompliziert. Also, meine Fragen sind:
- Ist eine solche Lösung besser als die oben vorgeschlagene?
- Gibt es eine ähnliche gebrauchsfertige Lösung für mathematische Operationen?
- Ist die Leistung einer solchen Lösung akzeptabel?
Vielen Dank im Voraus für Ihre Antworten
Grüße
[Generics Constraints] (http://docwiki.embarcadero.com/RADStudio/de/Constraints_in_Generics) können weder Ordinalwerte noch Gleitkommazahlen definieren. Dies ist, was Sie hier sehen, da jedes 'T' keine arithmetischen Operatoren hat. –
Einige Tests hier mit Generika und arithmetischen Operatoren durchgeführt: https://delphihaven.wordpress.com/2011/03/18/generic-arithmetic/. –
* "Generics in Delphi sind im Gegensatz zu Vorlagen in C++ oder generischen Typen in C#. Vor allem kann ein Typparameter nicht auf einen bestimmten einfachen Typ beschränkt werden, wie Integer, Double, String und so weiter." * [Link] (http://docwiki.embarcadero.com/RADStudio/en/Overloads_and_Type_Compatibility_in_Generics) –