2011-01-08 9 views
6

Estoy en D2010, en el que me tengo que quedar hasta que salga el bit de 64 bits.¿Los punteros a los tipos genéricos son compatibles con Delphi XE?

Con los genéricos, los punteros a los tipos genéricos no son compatibles, y me parece que son muy útiles. Leí en otro lugar en SO (publicación de 2009) Sir Barry Kelly pensó que esto bien podría cambiar en el futuro. ¿Alguien sabe si esto es compatible con XE?

Si no, realmente espero que se pongan en XE2.

Gracias.

Respuesta

2

NOTA: La siguiente respuesta es errónea, comenzando como lo hace desde una premisa defectuosa. En lugar de redactar todo para guardar mis rubores, lo dejé intacto para que los comentarios que resaltan el error tengan sentido,

¿Cómo se puede admitir esto de forma segura?

Dada (si esto es lo que tienes en mente, que creo que es):

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

Entonces, si tenemos:

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

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

A continuación, ambos de los siguientes sería permisible:

p := @a; 

    p := @b; 

en un momento dado p poder eliminar la referencia a cualquier TFoo de T, pero en un momento dado solo puede hacer referencia a un específico. No puedo ver ningún mecanismo de tiempo de compilación seguro para que las desreferencias de código p correctamente.

Una forma de evitar este problema (no una limitación del compilador, sino una limitación de intentar expresar algo de una manera segura, para la cual la seguridad del tipo simplemente no se puede expresar) sería crear derivados de tipo específico de estos tipos y usarlos. En el punto en el que desea eliminar la referencia que está casi seguro que va a saber el tipo T todos modos:

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 

Esto es posible incluso en Delphi 2010.

Sin embargo, preocupante, en la investigación de este I encuentra que:

p := @a; // Should not compile 

DOES de hecho compilar. Lo cual me parece erróneo. Muy mal. Y podría señalar (aún) otro defecto en la implementación de genéricos en Delphi.

Aquí hay dragones ...

+4

Dragons en este caso ;-). –

+0

+1 Muy buena redacción. ¿Has hecho un QC de tu hallazgo de lo que se compila pero no se debe compilar? –

+0

@Marjan: No. En primer lugar, no tengo acceso a XE para confirmar que la falla todavía existe; si ya se ha corregido en XE, no tiene sentido informarlo en contra de 2010, ya que no se lanzarán nuevas soluciones para 2010. En segundo lugar, puede ser una consecuencia del hecho de que la clase genérica TFoo no hace referencia realmente al tipo T. Si lo hizo, el compilador puede ser más estricto; no he probado esta hipótesis (sin embargo, en caso de que no compile en cualquier caso). Pero, por lo tanto, mi observación de que "podría" señalar un defecto, no es que definitivamente lo haga. :) – Deltics

5

En XE (2011):

esto funciona:

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

    TTest2<T> = array of T; 

esto no funcionará:

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

Así punteros a los genéricos no son todavía posibles.

Pero se puede hacer lo siguiente:

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; 

No se puede tener funciones genéricas, pero puede tener métodos genéricos.

Así que con esto puede tener sugerencias para genéricos, pero recuerde que no tiene ningún tipo de seguridad con esta técnica sucia.

2

Los apuntadores de Afaik solo se admiten anidados dentro del genérico.

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

utilizo este modo que pueda cambiar fácilmente el código de imagen de tratamiento (entero T = 8,16,32-bit o registro RGBA) por tipo. Acabo de cambiar la especialización, y el código, que usa los tipos anidados, se adapta.

Por supuesto, como con todos los genéricos, solo puede usar el tipo especializado, ya que no se genera código para ningún código con tipos genéricos no especializados. (solo se guarda hasta el momento de la especialización)

Actualización: Desafortunadamente, me encontré con http://qc.embarcadero.com/wc/qcmain.aspx?d=99703.

+0

Tenga en cuenta que [QualityCentral ahora se ha cerrado] (https://community.embarcadero.com/blogs/entry/quality-keeps-moving-forward), por lo que ya no puede acceder a los enlaces 'qc.embarcadero.com' . Si necesita acceder a datos antiguos de control de calidad, consulte [QCScraper] (http://www.uweraabe.de/Blog/2017/06/09/how-to-save-qualitycentral/). –

+0

Los he rastreado a través de los años mediante la descarga de pruebas. En Seattle mis diversos informes fueron corregidos (en realidad en XE7, pero una regresión lo ocultó). y una versión genérica de este código funciona: https://stackoverflow.com/questions/848025/rotating-bitmaps-in-code –

Cuestiones relacionadas