2014-08-28 28 views
1

請注意,這不是Pointer to generic type的重複。這是一個後續問題。通用記錄指針

我知道有可能定義一個指向任何泛型類型的指針。
只是Delphi讓它變得複雜。它本來是不可能的,但是由於編譯器錯誤,這個選項滑過了。
這是鏈接問題的答案。

我的問題是:

如何定義一個指針指向一個通用的記錄,而不在周圍類封裝呢?

示例代碼:

TGenericRecord<T> = record 
    Data: integer; 
    Procedure SomeMethod; inline; <<<< inlining is vital here. 
end; 

我希望得到一個類型安全的指針TGenericRecord。
我做不是想包裝在周圍的類記錄,因爲在我的實驗中,我發現,禁用內聯。

如何獲得一個類型安全的通用指針到這個記錄。

使用情況

{class} function create(size: integer): PGenericRecord{<T>} 

我希望能夠在除了在堆棧中,在堆上創建記錄。

+1

您可以在記錄中聲明'Type PT =^T;'並將其用作'var: m:TMiniStack .PT;':'m:= TMiniStack .Create;'。 – 2014-08-28 11:19:00

+0

不,它不是,因爲這個問題沒有答:不提供答案和B:我已經知道如何使一個指針在泛型類型本身內進行操作。我正在向你提到的那個問一個具體的跟進問題。 – Johan 2014-08-28 11:20:05

+0

@LURD,我對^ T不感興趣,我想要一個'^ TMiniStack '。 – Johan 2014-08-28 11:21:05

回答

2

我覺得你最好的選擇可能是這樣的:

type 
    TMyStaticClass<T> = class 
    public 
    type 
     TRec = record 
     .... 
     end; 
     PRec = ^TRec; 
    public 
    class function NewRec: PRec; static; 
    end; 

我沒有編譯器方便,以檢查是否這甚至編譯但我覺得它應該.....

+0

它編譯後(向記錄添加Integer併爲NewRec添加實現並更正語法錯誤 - ''應該在名稱後面,而不是在'class'之後)。 – 2014-08-28 13:48:39

+0

@Rudy感謝那 – 2014-08-28 14:10:57

+0

我會發布類似的解決方案。唯一的缺點是你必須將這種類型定義爲「TMyStaticClass .PRec」而不是簡單的「PRec」。我猜一旦'SomeType'已知,就可以創建一個別名。 – 2014-08-28 14:44:40

0

對David提出的答案進行了長時間評論,概述了我提取的解決方案。

以下編譯和工作。

首先像往常一樣創建記錄,但添加一個Free過程來釋放任何基於堆的實例。

type 
    TMiniStack<T> = record 
    private 
    SP: Integer; 
    Items: array[0..StackSize - 1] of T; 
    function GetItem(index: Integer): T; inline; 
    public 
    procedure Free; 
    procedure Init; inline; 
    function Pop: T; inline; 
    procedure Push(const Item: T); inline; 
    .... 
    end; 

比創建靜態保持類,該類定義指向泛型類型的指針。
請注意,靜態類沒有任何數據成員,您甚至可以將其抽象以確保它不被實例化。

MiniStack<T> = class 
    public type 
    PStack = ^Stack; 
    Stack = TMiniStack<T>; 
    public 
    class function Create(StackDepth: integer = DefaultStackSize): PStack; 
    end; 

Create是有點用詞不當,因爲它不會創建MiniStack<T>,但TMiniStack<T>

創建函數的實現如下:

class function MiniStack<T>.Create(StackDepth: integer = DefaultStackSize): PStack; 
begin 
    Result:= AllocMem(SizeOf(TMiniStack<T>) + 
      ((StackDepth - DefaultStackSize) * SizeOf(T))); 
end; 

唯一剩下要做的就是要創造一個特定的pstack在使用任何環境中的PStack的別名。

測試按預期工作。

type 
    PStack = MiniStack<Integer>.PStack; 

procedure TMyTestObject.TestStack; 
var 
    MyHeapStack: PStack; 
begin 
    MyHeapStack:= MiniStack<Integer>.Create; 
    try 
    MyHeapStack.Push(100); 
    MyHeapStack.Push(101); 
    MyHeapStack.Push(102); 
    Assert.IsTrue(MyHeapStack.Pop = 102); 
    Assert.IsTrue(MyHeapStack.Pop = 101); 
    Assert.IsTrue(MyHeapStack.Pop = 100); 
    finally 
    MyHeapStack.Free; 
    end; 
end; 

最重要的事是,內聯(重要的ministack的速度(每個電話只有2或3的CPU指令))仍然有效,這個解決方案。

+0

這不就是我說的嗎?對我來說,這是一個潛在的優秀問題,受到你班級所有細節的影響。按照我的回答精神,如果你能把問題歸結爲最微不足道的例子,那將是非常好的。使用一般類型名稱。並刪除這個答案。然後我們可以提出一個適用於未來訪問者的問答。 – 2014-08-28 19:55:48

+0

只要我在鍵盤後面而不是在iphone上, – Johan 2014-09-01 22:14:17