5


3

与えられた効率的なポインタベースのハッシュマップ実装を一般的なハッシュマップ実装に変換する過程で、私は以下の問題に出会った。

ハッシュノードを表すクラスがあります(ハッシュマップ実装はバイナリツリーを使用します)

THashNode = class public Key:KEY_TYPE;値:VALUE_TYPE;左:THashNode。右:THashNode。終わり;

それに加えて、ハッシュノードへのポインタを返すべき関数があります。 書きたかった

PHashNode = ^ THashNode

しかし、それはコンパイルされません( ';'は予期されていましたが、 '<'が見つかりました)。

ジェネリック型へのポインタを取得する方法

そして、Barry Kellyに訴えました。あなたがこれを読むならば:はい、これはあなたのハッシュマップ実装に基づいています。 あなたはあなた自身の実装のそのような一般的なバージョンをあなた自身で書かなかったでしょう? それは私に時間を節約するでしょう :)

4 Answer


11


すみません。 ジェネリックポインタ型はサポートされていないため、オープンジェネリック型へのポインタはサポートされていません。この「機能」は、私たちが誰かのコードを壊した場合に備えて、アップデートから削除することはできません。 ジェネリックポインタ型に対する制限は将来削除されるべきですが、いつ約束することはできません。

問題の型が私が書いた JclStrHashMap`のもの(あるいは古代の HashList`ユニット)であるなら、それを再現する最も簡単な方法はノード型をクラスに変更してダブルポインタを迂回することです。適切なキャストの `Pointer`として。 しかし、そのユニットを今日も書いているのであれば、バケットをバイナリツリーとして実装することはしないでしょう。 Generics.Collectionsユニットで辞書を書く機会が得られましたが、他のすべてのDelphiコンパイラでは、出荷前の堅実なQAのためには作業時間が厳しすぎ、汎用機能のサポート自体はかなり遅れて流動的でした。

ハッシュマップバケットは、ダブルハッシング、バケットごとの動的配列、または連続した配列からのセルのリンクリストのいずれかとして、代表的なデータを使用したテストから得られるものとして実装することをお勧めします。 論理は、ツリー/リスト内のリンクをたどることによるキャッシュミスのコストが、優れたハッシュ関数を使用してツリーとリスト間のバケット検索の違いを支配するはずであるというものです。 現在の辞書は、主に比較的簡単に実装でき、利用可能な基本的な総称操作のセットを使用して作業していたため、ストレート・リニア・プロービングとして実装されています。

とは言っても、バイナリツリーバケットは貧弱なハッシュ関数に対する効果的なヘッジであるべきでした。もしそれらがバランスのとれた二分木であれば( `⇒`さらに修正コスト)、それらは平均O(1)そしてO(log n)最悪の場合の性能になるでしょう。


4


実際にあなたの質問に答えるためには、 "ジェネリック型"は存在しないのでジェネリック型へのポインタを作ることはできません。 型パラメータを入力して、特定の型へのポインタを作成する必要があります。

残念ながら、コンパイラは^の後に山括弧を見つけるのが嫌いです。 しかし、それは以下を受け入れます:

   TGeneric = record
      value: T;
   end;

   TSpecific = TGeneric;

   PGeneric = ^TSpecific;

しかし、 "` PGeneric = ^ TGeneric; `"はコンパイラエラーになります。 私にとってはグリッチのようですね。 私があなただったらQCでそれを報告したいと思います。

とにかく、あなたはなぜオブジェクトへのポインタを作ろうとしているのですか? Delphiオブジェクトは参照型なので、すでにポインタです。 オブジェクト参照をPointerにキャストするだけでいいのです。


4


Delphiが総称ポインタ型をサポートしている場合は、次のようになります。

タイプPHashNode = ^ THashNode;

つまり、左側にある型の名前を宣言する一般的なパラメータについて説明してから、右側にある型を作成するときにそれらのパラメータを使用します。

ただし、Delphiはそれをサポートしていません。 QC 66584を参照してください。

その一方で、私はクラス型へのポインタを持っている必要性についても疑問を投げかける。 一般的かどうか。 それらはまれに必要なだけです。


2


Generics.CollectionsユニットにTDictionaryという汎用ハッシュマップがあります。 残念ながら、現時点では非常に壊れていますが、アップデート#3で修正される予定です。ニックホッジスへ。