2016-10-15 17 views
5

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

私はそれを使用します。このコードで

これはうまくいきます。

これで、Delphiの同等のコードを記述する必要があります。上記のC++コードに基づいて、Delphi Genericクラスを作成しようとしました。

ただし、このコードはコンパイルされません。私はこのエラーを取得する:このコードは私の知る限り

E2015 Operator not applicable to this operand type

は動作するはずです、と私はそれと間違っているかを理解していません。誰にでも私に説明することができます:

  1. なぜこのようなコードはDelphiでコンパイルされませんか?

  2. Add()関数を提供するテンプレートクラスを作成するための正しい(最も単純な)方法は、C++コードと上記の使用法に可能な限り近いものですか?

は2016年10月17日にすべての返信用

感謝を編集しました。だから私が正しく理解していれば、DelphiはC++には存在しないいくつかの制約を課しているので、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)を使用する必要性。上記のコードに関して、私の質問は次のとおりです。

  1. このソリューションは良い解決策ですか? (例:APointF、APointI、APointD、...のように、サポートしたいタイプごとに各レコードのバージョンを書く方が良い)
  2. このコードを簡略化する方法はありますか? APointF(pt)変換なしで直接pt.m_Xを呼び出すソリューションですか? (変数に直接アクセスするよりもエレガントだと思っても、プロパティの実装は省略しました)
  3. このソリューションのパフォーマンスはどうですか? (つまり、このソリューションは、直接m_X:= m_X +値の加算よりも大幅に遅くなりますか?

    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; 
    

    私は、シーンの背後にあるコードを読み取ろうとしました。)

最後に、私はこの方法2つのジェネリック型の等価比較を実現することが可能であるDelphiコード、内の別の解決策を見てしかし、私はそれがひどく複雑であることが分かった。だから、私の質問は次の通りです:

  1. このような解決法は、上記の解決策よりも優れていますか?
  2. すぐに使用できる、数学的操作のためのソリューションはありますか?
  3. このようなソリューションのパフォーマンスは受け入れられますか?

ご回答を事前に感謝

よろしく

+0

[ジェネリックス制約](http://docwiki.embarcadero.com/RADStudio/ja/Constraints_in_Generics)は、定規も浮動小数点も定義できません。これは、すべての 'T 'に算術演算子がないので、ここで見ているものです。 –

+0

いくつかのテストは、ジェネリックスと算術演算子でここで行われました:https://delphihaven.wordpress.com/2011/03/18/generic-arithmetic/。 –

+0

*デルファイのジェネリックスは、C++のテンプレートやC#のジェネリック型とは異なります。特に、型パラメータは、Integer、Double、Stringなどの特定の単純型に制約することはできません。 http://docwiki.embarcadero.com/RADStudio/en/Overloads_and_Type_Compatibility_in_Generics) –

答えて

4

Delphiのジェネリック医薬品がジェネリック型に作用する算術演算子をサポートしていません。コンパイラがコードを受け入れるには、ジェネリック型の各操作がインスタンス化時に利用可能になることを知る必要があります。

一般的な制約では、コンパイラにその型が持つ機能を伝えることができます。しかし、一般的な制約では、型がarithmetjc演算子をサポートしていることをコンパイラーに知らせることはできません。

残念ながら、あなたがしようとしていることは、単に不可能です。インターフェイスなどのツールを使用して算術演算を実行できるフレームワークを自分で作成できますが、そのようにするとパフォーマンスが低下します。それが妥当であれば問題ありません。それ以外の場合は、弾丸を噛んで、ジェネリックを避けるのが最善です。

Oh for C++テンプレート。

+0

確かに、C++のテンプレートは、私がC++から本当に見逃している2つの事柄の1つです。私は最近、線形代数ライブラリを書いて、実際の行列と複雑な行列を実装しました。 2つのケースのすべての基本コードを複製する必要がありました... –

5

Delphiジェネリックは、C++テンプレートと本質的に異なり、C#の対応するものと似ています。

C++では、テンプレートの種類に対して任意の操作を行うことができ、テンプレートのインスタンス化時に、使用している特定の型に対してテンプレートで実行している操作が利用可能であるかどうかがチェックされます。そうでなければ、コンパイラエラーが発生します。

Delphi(および他の多くの言語)では、いくつかの宣言的制約を提供する可能性があるジェネリック型を宣言します。これらの制約(基本クラスまたはインターフェイス)によってジェネリック型に対して実行できる操作が決定されます。インスタンス化時には、宣言された型が制約に適合するかどうかだけがチェックされます。

おそらく、Delphi言語は浮動小数点型または序数型の制約を追加する可能性がありますが、これは非常に限定された柔軟性を提供します(汎用インスタンスで使用できる浮動小数点型または整数型の変更)。私は個人的にこれを重要な特徴とは見なさない。

+3

演算子のオーバーロードは、言及されているタイプ以外のタイプで算術演算を実行できることを意味します。良い例は、複素数型ですが、さらに多くの種類があります。したがって、より多くの機能を欲するということは、組み込み型に限定されるものではありません。実際には、特定の演算子が定義されていることを要求するように型を制約することができれば幸いです。それが重要な機能であるかどうかについては、あなたが誰に尋ねるかによって明らかに異なります。私は、深刻な数値プログラミングを行う人は、算術とジェネリックプログラミングを組み合わせることができるというメリットがあると思います。 –

+2

デルファイは、豊富な数値処理のバックグラウンドから、ジェネリックの算術演算子の制約をサポートすることで確かに恩恵を受けるでしょう。 –

+0

これはDelphiでC++と比較して私が本当に間違っている2つの事の一つです。 –