¿Los punteros a tipos genéricos son compatibles con Delphi XE?

Estoy en D2010, en el que tengo que quedarme hasta que salga el de 64 bits.

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

Si no, realmente espero que se pongan en XE2.

Gracias.

preguntado el 08 de enero de 11 a las 20:01

3 Respuestas

Sobre 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;

Por lo tanto, aún no es posible hacer sugerencias sobre los genéricos.

Pero puedes 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 puede tener funciones genéricas, pero puede tener métodos genéricos.

Entonces, con esto, puede tener sugerencias para los genéricos, pero recuerde que no tiene seguridad de tipos al usar esta técnica sucia.

Respondido el 08 de enero de 11 a las 23:01

NOTA: La siguiente respuesta es Mal, ¡partiendo de una premisa defectuosa! En lugar de redactar todo para salvar mis sonrojos, lo dejé intacto para que los comentarios que resaltan el error tengan sentido,

¿Cómo se puede apoyar esto de manera segura?

Dado (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;

Entonces se permitirían los dos siguientes:

  p := @a;

  p := @b;

En cualquier momento dado p podría desreferenciar a cualquier TFoo de T, pero en un momento dado solo puede hacer referencia a un T. No puedo ver ningún mecanismo de tiempo de compilación seguro para garantizar que el código elimine las referencias p correctamente.

Una forma de solucionar este problema (no una limitación del compilador, sino una limitación de intentar expresar algo de una manera segura de tipos para la cual la seguridad de tipos simplemente no se puede expresar) sería crear derivados específicos de tipo de estos tipos y usar esos. En el punto en el que desee eliminar la referencia, es casi seguro que sabrá el tipo T de todas formas:

  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, de manera preocupante, al investigar esto, encuentro que:

  p := @a;  // Should not compile

De hecho, se compila. Lo que me parece incorrecto. Muy mal. Y podría señalar (aún) otra falla en la implementación de genéricos en Delphi.

Aquí hay dragones...

Respondido el 09 de enero de 11 a las 01:01

+1 Muy buena redacción. ¿Ha realizado un control de calidad sobre lo que se compila pero no debe compilar? - Marjan Venema

@Marjan: No. En primer lugar, no tengo acceso a XE para confirmar que el error aún existe; si ya se ha solucionado en XE, no tiene sentido informarlo en 2010, ya que no habrá más correcciones para 2010 lanzadas. En segundo lugar, puede ser una consecuencia del hecho de que la clase genérica TFoo en realidad no hace referencia al tipo T. Si lo hizo, el compilador puede ser más estricto; sin embargo, no he probado esta hipótesis (fwiw, en mi humilde opinión, debería fallar al compilar en cualquier caso). Pero de ahí mi observación de que "podría" señalar un defecto, no que definitivamente lo haga. :) - Deltics

El operador @ no se escribe de forma predeterminada en Delphi; es por eso que no está recibiendo diagnósticos. Enciende con {$T+}. Además, es perfectamente posible, en principio, tener punteros genéricos en Delphi (aunque no están implementados). Su primer conjunto de código de ejemplo está mal. A (teórico) p: PFoo<T> sería compatible con las direcciones de ubicaciones de tipo TFoo<T>, donde estamos hablando de lo mismo T. Entonces, si p es del tipo PFoo<Integer>, sería compatible con @a si a: TFoo<Integer>, Pero no a: TFoo<string>. - Barry Kelly

-1 Como señala Barry, este análisis es defectuoso. Sinceramente, no puedo creer que alguien en su sano juicio funcione en modo {$ T-}. ¿Alguien realmente lo hace? Y si es así, ¿por qué? - David Heffernan

@David: Cuando trabaje con punteros, debe saber lo que está haciendo ... si necesita que el compilador lo sostenga en el camino, entonces probablemente no debería jugar con los punteros en primer lugar. Estoy de acuerdo en que el sistema de tipos debería funcionar con usted, el problema es que el operador @ tipeado tiene solo un conocimiento parcial del sistema de tipos, y cuando se encuentra con esa limitación, lo obstaculiza positivamente, en lugar de ayudar. - Deltics

Los punteros de Afaik a tipos genéricos solo se admiten anidados dentro del genérico.

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

Utilizo esto para poder cambiar fácilmente el código de procesamiento de imágenes (T = entero de 8,16,32 bits o registro RGBA) por tipo. Simplemente cambio 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)

Actualizar: Me encontré con http://qc.embarcadero.com/wc/qcmain.aspx?d=99703 Desafortunadamente.

Respondido 27 Abr '13, 23:04

Tenga en cuenta que QualityCentral ahora se ha cerrado, entonces no puedes acceder qc.embarcadero.com enlaces más. Si necesita acceder a datos antiguos de control de calidad, consulte QCScraper. - Remy Lebeau

Los he seguido a lo largo 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 oscureció). y funciona una versión genérica de este código: stackoverflow.com/questions/848025/rotating-bitmaps-in-code - Marco van de Voort

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.