3

HashTable があり、not_found結果を返す方法が必要です。

type
  TCell<T> = record
  .....
    property key: cardinal read FKey write FKey;
    property data: T read FData write FData;
  end;

  THashTable<T> = class(TEnumerable<T>)
  private
    FCells: array of TCell<T>;
    FEmpty: T;
  ...
    constructor Create(InitialSize: cardinal); overload;
    function Lookup(key: cardinal): T;
  ...
  end;

constructor THashTable<T>.Create(InitialSize: cardinal);
begin
  inherited Create;
  // Initialize regular cells
  FArraySize:= InitialSize;
  Assert((FArraySize and (FArraySize - 1)) = 0); // Must be a power of 2
  SetLength(FCells, FArraySize);

  FillChar(FEmpty, SizeOf(FEmpty), #0);  //Superfluous I know, just there to
                                         //demonstrate the point. 
end;

上記の構造を考えると、どうすればnot found結果を返すことができますか?
ポインターがあれば、へのnilポインターを返しますT
ただし、ジェネリック型へのポインターは許可されていません。

だから私は以下の解決策を思いついた:

function THashTable<T>.Lookup(key: cardinal): T;
var
  Cell: NativeUInt;
begin
  if (key <> 0) then begin
    // Check regular cells
    Cell:= First_Cell(IntegerHash(key));
    while (true) do begin
      if (FCells[Cell].key = key) then Exit(FCells[Cell].data);
      if not (FCells[Cell].key = 0) then Exit(FEmpty);  <<-- is this correct?
      Cell:= Circular_Next(Cell);
    end;
  end else begin
    Result:= FEmpty;   <<--- Can I return an empty generic like this?
  end;
end;

ゼロで初期化されたジェネリックを意味に返すことはできますno resultか?

または、構造化されたタイプ(クラス/レコード/バリアント/文字列など)で問題が発生しますか。

Tが整数であるときのあいまいさを理解していることに注意してください。ゼロは有効な値である可能性が非常に高いため、not_found と区別できません。
私はそれらの結果について心配していません。

4

4 に答える 4

3

varデータに出力パラメーターを使用するように関数を変更することをお勧めします。次に、 に aBooleanを使用できますResult

function THashTable<T>.Lookup(key: cardinal; var Value: T): Boolean;
var
  Cell: NativeUInt;
begin
  Result := False;
  if (key <> 0) then begin
    // Check regular cells
    Cell := First_Cell(IntegerHash(key));
    while Cell <> -1 do begin
      if (FCells[Cell].key = key) then begin
        Value := FCells[Cell].data;
        Exit(True);
      end;
      if (FCells[Cell].key <> 0) then Break;
      Cell := Circular_Next(Cell);
    end;
  end;
end;
于 2013-10-07T06:36:12.383 に答える
0

代わりに、ジェネリック型へのポインターを返すことにしました。

type 
  //P<T> = ^T;
  P<T> = record {holding a pointer to T with some operator overloading}

  ....
  FCells: array of T <<-- holds T directly now.

function THashTable<K,T>.Lookup(const key: K): P<T>;
begin
  ....
  if found then Result:= @FCells[CorrectIndex]
  else Result:= nil;
end; 
于 2013-10-08T16:39:35.947 に答える