2013-10-07 3 views
0

나는이 문제를 해결하기 위해 노력하고있어 (외에 몇 사람을.)연산자 오버로딩을 사용하여 제네릭 형식에 대한 포인터를 만들 수 있습니까?

문제

//None of these compile 
type 
    PAType<T> = ^AType<T>; 
    P<T> = ^T;     
    PAType = ^AType<T> 

그래서 내가 기록 및 연산자 오버로드를 사용하여 내 자신의 롤 노력하고있어.

다음 코드를 쓰고 있어요 : 나는 해시 테이블을 쓰고 있어요

TCell<T> = record 
    private 
    FData: T; 
    procedure SetData(Value: T); inline; 
    function GetData: T; inline; 
    public 
    property data: T read GetData write SetData; 
    end; 

    //Type safe pointer to T, because it knows SizeOf(T). 
    P<T> = record //wrapper around pointer: ^TCell<T>;^H^H^H^H any <T> actually 
    private 
    FPointerToT: pointer; 
    public 
    class operator Implicit(a: pointer): P<T>; inline; 
    class operator Implicit(a: P<T>): pointer; inline; 
    class operator Implicit(Cell: TCell<T>): P<T>; inline; 
    class operator Implicit(p: P<T>): TCell<T>; inline; 
    class operator Add(a: P<T>; b: NativeUInt): P<T>; inline; 
    class operator NotEqual(a,b : P<T>): Boolean; inline; 
    class operator NotEqual(a: P<T>; b: pointer): Boolean; inline; 
    class operator Equal(a,b : P<T>): Boolean; inline; 
    class operator GreaterThan(a,b : P<T>): Boolean; inline; 
    class operator GreaterThanOrEqual(a,b : P<T>): Boolean; inline; 
    class operator LessThan(a,b : P<T>): Boolean; inline; 
    class operator LessThanOrEqual(a,b : P<T>): Boolean; inline; 
    class operator Inc(a: P<T>): P<T>; inline; 
    class operator Dec(a: P<T>): P<T>; inline; 
    class operator Explicit(a: P<T>): T; inline; 
    end; 

. 왜냐하면 나는 해싱을위한 다른 옵션을 시도하고 있기 때문이다.
해시 테이블은 데이터가있는 레코드를 가져와 동적 배열 (레코드 자체, 은 포인터가 아니고이 아님)에 레코드를 저장하고 해당 레코드에 대한 포인터를 반환해야합니다.

이렇게하면 응용 프로그램이 다소 차이가있는 순차적 인 순서로 데이터를 저장할 수 있습니다. 캐시에 유용합니다.
해시 테이블은 한 번에 하나의 유형 만 보유하고 있지만 다른 해시 테이블에 해시 될 다른 클래스가 있기 때문에 제네릭을 사용하려고합니다.

포인터를 반환함으로써 이중 저장을 방지합니다.

미완성 구조는 위의 날과 같이 코드를 작성할 수 있습니다 : 나는 미스를 의미하는 Nullable<T> 필요하지 않습니다

//FCells: array of T; 
//FArrayEnd: pointer; //points to element FCells[max_elements+1] (i.e. access violation) 

function THashTable<K, T>.NextItem(Item: P<T>): P<T>; 
begin 
    Result:= Item + SizeOf(T); //pointer arithmetic 
    if Result >= FArrayEnd then Result:= @FCells[0]; //comparison and assignment 
end; 

function THashTable<K, T>.Lookup(const key: K): P<T>; 
var 
    Index: NativeUInt; 
    ItemKey: K; 
begin 
    if IsValid(key) then begin 
    // Check regular cells 
    Index:= First_Cell(FGetHashFromKey(key)); //FGet.. is a user supplied key generation proc. 
    while (true) do begin 
     ItemKey:= FGetKey(FCells[Index]); 
     if (IsEqual(ItemKey, key)) then exit(@FCells[Index]); 
     if (IsEmpty(ItemKey)) then exit(nil); //nil pointers denote no-hit 
     Index:= NextIndex(Index); 
    end; 
    end 
    else { if IsEmpty(key) then } begin 
    // Check zero cell 
    Result:= @FZeroCell; 
    end; 
end; 

참고. 나는 표준 nil 포인터가 작동합니다.

나는 타입 캐스트를 할 필요가 없으며 포인터가 얼마나 큰지 알고 있습니다.
무엇을 알고 있습니까?T입니다.

내가 그렇게 제네릭으로 잡았다의 많은, 거기에 알고

내가 너무 깊이에 들어가기 전에

.
이 방법이 (원칙적으로) 작동합니까, 아니면이 방법이 단지 희망적인 사고입니까?

+0

:

type THashTable<K, T> = class public type TCell = TCell<T>; PCell = ^TCell; public function NextItem(Item: PCell): PCell; end; 

포인터 연산을 구현하려면이 코드가 필요합니다. 당신의 실제 문제는 무엇입니까? "Generic Types에 대한 포인터를 가지고 있지 않으면 안됩니다." –

+0

최소한의 작업 솔루션을 얻 자마자 나는 스스로 답할 것입니다. – Johan

+0

질문을 수정하지 않고 그렇게하지 마십시오. 나는 진실로 관심이있다. 귀하가 발견 한 한계를 알려주십시오. –

답변

3

일반 유형에 대한 포인터를 가질 수 있습니다. 이처럼 : 나는 여기에 질문을 식별 할 수

function THashTable<K, T>.NextItem(Item: PCell): PCell; 
begin 
    Result := Item; 
    inc(Result); 
end; 
+0

그 트릭을 알고 있지만 클래스의 ** 외부 **에서 포인터를 선언하고 선언하면 작동하지 않습니다. 다른 클래스/유닛에서 포인터 ** 유형 **을 사용할 수 있어야합니다. – Johan

+0

요구 사항을 다 풀었 으면 질문에 넣어주십시오. 어쨌든, 유형 밖에서 그 유형을 사용할 수 있습니다. 그것은'THashTable .PCell'입니다. –

+0

잠깐, 어디서나 접근 가능한'TCell'과'PCell' 타입이 있습니까? 예, 그들은 멋집니다. – Johan

관련 문제