Поддерживаются ли указатели на универсальные типы в Delphi XE? - PullRequest
6 голосов
/ 08 января 2011

Я на D2010, на котором я должен остаться, пока не выйдет 64 бит.

С универсальными типами указатели на универсальные типы не поддерживаются, и я считаю, что они действительно очень полезны.Я читал в другом месте на SO (сообщение 2009 года), сэр Барри Келли думал, что это может измениться в будущем.Кто-нибудь знает, поддерживается ли это в XE?

Если нет, то я очень надеюсь, что их поместят в XE2.

Спасибо.

Ответы [ 3 ]

5 голосов
/ 08 января 2011

На XE (2011):

Это работает:

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

  TTest2<T> = array of T;

Это не будет работать:

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

Так что указатели на дженерики пока невозможны.

Но вы можете сделать следующее:

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;

У вас не может быть универсальных функций, но у вас могут быть универсальные методы.

Таким образом, вы можетеиметь указатели на дженерики, но помните, что у вас нет безопасности типов при использовании этой грязной техники.

2 голосов
/ 09 января 2011

Afaik указатели на универсальные типы поддерживаются только вложенными в универсальные типы.

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

Я использую это, чтобы легко переключать код обработки изображения (T = 8,16,32-битное целое число или запись RGBA) по типу.Я просто переключаю специализацию, и код, который использует вложенные типы, адаптируется.

Конечно, как и во всех обобщенных типах, вы можете использовать только специализированный тип, так как никакой код не генерируется для любого кода с универсальными, неспециализированные виды.(сохраняется только до времени специализации)

Обновление: Я столкнулся с http://qc.embarcadero.com/wc/qcmain.aspx?d=99703 к сожалению.

2 голосов
/ 08 января 2011

ПРИМЕЧАНИЕ. Следующий ответ - неверно , начиная с ошибочной предпосылки!Вместо того, чтобы отредактировать всю вещь, чтобы сохранить мои румяна, я оставил ее нетронутой, чтобы комментарии, освещающие ошибку, имели смысл,

Как это можно безопасно поддерживать?

Учитывая(если это то, что вы имеете в виду, и я думаю, что это так):

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

Тогда, если мы имеем:

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

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

Тогда допустимы оба следующих условия:

  p := @a;

  p := @b;

В любой момент времени p может разыменовываться к любому TFoo T , но в любой момент времени он может ссылаться только на конкретный T *.1023 *.Я не вижу какого-либо безопасного для времени механизма компиляции для обеспечения правильного разыменования кода p .

Один из способов обойти эту проблему (не ограничение компилятора, а ограничение попыткичтобы выразить что-либо безопасным для типа способом, для которого безопасность типа просто не может быть выражена), было бы создать специфичные для типа производные этих типов и использовать их.В момент, когда вы хотите разыменовать, вы почти наверняка узнаете тип T :

  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

Это возможно даже в Delphi 2010.

Однако, что неприятно, при исследовании этого я обнаружил, что:

  p := @a;  // Should not compile

действительно компилируется.Что мне кажется неправильным.Очень неправильно.И может указать (еще) на еще один недостаток в реализации обобщений в Delphi.

Здесь будут драконы ...

...