2017-11-07 14 views
14

私はC++とDelphiを比較していました。Delphiのネストされたクラス

これは非常に簡単なC++コードです。このシナリオでは

template<typename T> 
class C { 

class D { 
    T x; 
} 

} 

、私たちはクラスCはテンプレートクラス(=ジェネリッククラス)で、ネストされたクラスDもテンプレートクラスであることを持っています。 Tdoubleである場合、の中のxdoubleです。

私はこれを言うことができない:私はすでにC「内部」だと、別のTが競合になるので、

template<typename T> 
class C { 

template<typename T> 
class D { 
    T x; 
} 

} 

エラーであること。エラーを修正するには、Uのような別の名前を使用する必要があります。

template<typename T> 
class C { 

template<typename U> 
class D { 
    T x; 
} 

} 

Delphiでは、私はこれを書くことができる:Txは以来integerある今、integerある

type 
TClassC<T> = class 
    private 

    type 
    TClassD = class 
    private 
     x: T; 
    end; 

end; 

場合(私はオンライン読んで理解した内容から)TClassDintegerです。デルファイでは、これも法的です:

type 
TClassC<T> = class 
    private 

    type 
    TClassD<T> = class // <-- note the <T> repeated!! 
    private 
     x: T; 
    end; 

end; 

現在はどうなっていますか? をTClassDに再度宣言できれば、これは<T>がなければTClassDクラスではないことを意味します。私は正しいですか?

+3

これをチェックするのは簡単なはずですが、このコードをコンパイルすると内側のTが外側のものを隠すことが予想されます。つまり、内部の型パラメータに別の名前を使用したのと同じです。 'TClassC 'や 'TClassD 'のようなものです。 –

+0

言い換えれば、私の期待は、Delphiコードが、パラメータ名が衝突しないC++バージョンとまったく同じように動作することです。しかし、C++言語は名前の衝突からあなたを守ります。 –

+0

あなたの最初のC++の例では、 'D'自体がテンプレートクラスではなく、' C'のテンプレートは範囲内にあり、 'D'はそれを使用できます。あなたの2番目のC++の例では、 'T 'という名前の2つのテンプレートパラメータを持つことは、実際には名前の競合です。なぜならC++は同じスコープ内で繰り返し識別子を好きではないからです。 Delphiジェネリックスは、C++テンプレートと同じ構文ではありません(同様の構文を使用していても)、DelphiはC++よりもこの特定の例で少し柔軟です。 –

答えて

12

この単純なプログラムを検討:このプログラムはコンパイルが、以下のヒント発する

type 
    TClassC<T> = class 
    private 
    type 
    TClassD<T> = class 
    private 
     x: T; 
    end; 
    end; 

var 
    obj: TClassC<Integer>.TClassD<string>; 

begin 
    obj := TClassC<Integer>.TClassD<string>.Create; 
    obj.x := 42; 
end. 

を:

[DCC32ヒント]:コンテナ・タイプ

の型パラメータを持つH2509識別子 'T' の競合を

xは、インナーではなく外部の汎用パラメーターから型を取得することが割り当てによって証明されます。

私はこれを驚いたと言わざるを得ませんでした。私は内側のジェネリックパラメータがで、外側がであることを期待していました。実際、私が知る限りでは、内部型がその汎用パラメータを参照する方法はありません。

両方の汎用パラメータを参照できるようにするには、異なる名前を使用する必要があります。例:

type 
    TClassC<T1> = class 
    private 
    type 
    TClassD<T2> = class 
    private 
     x: T2; 
    end; 
    end; 

これは、同種のC++テンプレートコードが強制するものです。

私の見解では、この答えの先頭にあるコードをコンパイルすることは、Delphi言語の設計上の弱点です。

+1

これは実際には非常に予期しないものです。 –

+1

それは驚くべきことです。ヒントと警告は、たとえエラーがあったとしても、たとえコンパイラがまだ完了するまで実行されているとしても、通常は処理するという概念を強化しますが、 –

+3

@J ...私はヒントが非常に驚くべきことを見つける。何かこれが最も難解な側面です。開発者は、ヒントを出すように問題を十分に認識していましたが、それをそのままにしておいてください。彼らは何を考えていたのですか?これまで実現していたことが問題でしたが、ジェネリックパラメータを決して使用できないジェネリッククラスを受け入れるように、コンパイラをそのまま残すことに決めましたか? –

関連する問題