2011-01-08 13 views
6

Sono a D2010, su cui devo rimanere fino a quando il 64 bit non viene fuori.Puntatori a tipi generici supportati in Delphi XE?

Con i generici, i puntatori ai tipi generici non sono supportati e li troverei molto utili. Ho letto altrove su SO (pubblicazione nel 2009) Sir Barry Kelly ha pensato che questo potrebbe cambiare in futuro. Qualcuno sa se questo è supportato in XE?

In caso contrario, spero davvero che vengano inseriti in XE2.

Grazie.

risposta

2

NOTA: La seguente risposta è errata, che inizia come da una premessa imperfetta! Piuttosto che redarre l'intera cosa per salvare i miei rossori, l'ho lasciato intatto in modo che i commenti che evidenziano l'errore abbiano senso,

Come può essere supportato questo in modo sicuro?

Given (se questo è quello che hai in mente, che penso che sia):

type 
    TFoo<T> = class end; 
    PFoo<T> = ^TFoo<T>; 

Poi, se si ha:

var 
    a, b: TFoo<T>; 
    p: PFoo<T>; 

    a := TFoo<String>.Create; 
    b := TFoo<Integer>.Create; 

Poi entrambe le seguenti sarebbe ammissibile:

p := @a; 

    p := @b; 

In qualsiasi momento p potrebbe risolvere il riferimento a qualsiasi TFoo di T, ma in qualsiasi momento può sempre fare riferimento solo a uno specifico T. Non riesco a vedere alcun meccanismo di compilazione compatibile con i tipi per garantire che le code dereferences p correttamente.

Un modo per aggirare questo problema (non una limitazione del compilatore, ma una limitazione di cercare di esprimere qualcosa in modo sicuro tipo per il quale la sicurezza di tipo semplicemente non può essere espresso) sarebbe quello di creare derivati ​​specifici del tipo di questi tipi e li usano. Al punto in cui si vuole dereferenziare si è quasi certamente andando a conoscere il tipo T comunque:

type 
    TFoo<T> = class end; 

    TFooString = TFoo<String>; 
    PFooString = ^TFooString; 


    var 
    p: PFooString; 


    a := TFoo<Integer>; 
    b := TFoo<String>; 


    p := @a; // Should not compile 
    p := @b; // This is OK 

Questo è possibile anche in Delphi 2010.

Tuttavia, preoccupante, a indagare questo ho scoprire che:

p := @a; // Should not compile 

in effetti compilazione. Il che mi sembra sbagliato. Molto sbagliato. E potrebbe indicare (ancora) un altro difetto nell'implementazione dei generici in Delfi.

Ecco i draghi ...

+4

Draghi in questo caso ;-). –

+0

+1 Scrive molto bene. Hai fatto QC a trovare ciò che non dovrebbe essere compilato? –

+0

@ Marjan: no. Prima di tutto, non ho accesso a XE per confermare che il bug esista ancora - se è già stato risolto in XE allora non c'è motivo di segnalarlo contro il 2010 poiché non ci saranno ulteriori correzioni per il 2010 rilasciate. In secondo luogo, potrebbe essere una conseguenza del fatto che la classe generica TFoo in realtà non fa riferimento al tipo T. Se lo facesse, il compilatore potrebbe essere più severo - non ho ancora testato questa ipotesi (per esempio, dovrebbe non riuscire a compilare in ogni caso). Ma da qui la mia osservazione che "potrebbe" indicare un difetto, non che lo faccia assolutamente. :) – Deltics

5

On XE (2011):

questo funziona:

type 
    TTest1<T> = record 
    FX : T; 
    end; 

    TTest2<T> = array of T; 

questo non funzionerà:

type 
    TTest3<T> = ^TTest1<T>; 
    TTest4<T> = ^TTest2<T>; 
    TTest<T> = ^T; 

Quindi i puntatori ai farmaci generici non sono ancora possibili.

Ma è possibile effettuare le seguenti operazioni:

type 
    TMyClass = class 
    public 
    class function GetAddr<T>(const AItem: T): Pointer; 
    class function GetP<T>(const APtr: Pointer): T; 
    end; 

class function TMyClass.GetAddr<T>(const AItem: T): Pointer; 
begin 
    Result := @AItem; 
end; 

class function TMyClass.GetP<T>(const APtr: Pointer): T; 
begin 
    Result := T(APtr^); 
end; 

Non si può avere funzioni generiche, ma si può avere metodi generici.

Quindi con questo si è in grado di avere dei puntatori ai generici, ma ricorda che non hai alcun tipo di sicurezza usando questa tecnica sporca.

2

I puntatori Afaik a tipi generici sono supportati solo all'interno del generico.

Type 
    tbwimagegen <T > = Class(TBaseImage) 
      Type 
       TLocalType =tbwimagegen <T>; 
       BaseUnit = T; 
       RefT= ^BaseUnit; 
       end; 

utilizzo questa in modo che possa facilmente passare immagine codice di elaborazione (T = 8,16,32-bit integer o registrare RGBA) per tipo. Io cambio solo la specializzazione e il codice, che usa i tipi annidati, si adatta.

Ovviamente, come con tutti i generici, è possibile utilizzare solo il tipo specializzato, poiché non viene generato alcun codice per alcun codice con tipi generici e non specializzati. (viene salvato solo fino al momento della specializzazione)

Aggiornamento: Ho incontrato il http://qc.embarcadero.com/wc/qcmain.aspx?d=99703 sfortunatamente.

+0

Si noti che [QualityCentral è stato chiuso] (https://community.embarcadero.com/blogs/entry/quality-keeps-moving-forward), quindi non è più possibile accedere ai collegamenti 'qc.embarcadero.com' . Se è necessario accedere ai vecchi dati QC, consultare [QCScraper] (http://www.uweraabe.de/Blog/2017/06/09/how-to-save-qualitycentral/). –

+0

Li ho rintracciati nel corso degli anni scaricando le prove. A Seattle i miei vari rapporti sono stati corretti (in realtà in XE7, ma una regressione lo ha oscurato). e una versione generica di questo codice funziona: https://stackoverflow.com/questions/848025/rotating-bitmaps-in-code –