Как я могу объявить указатель на основе универсального типа? - PullRequest
9 голосов
/ 17 марта 2011

У меня есть такой класс:

type A = class
    procedure<T> DoStuff(tPtr: ^T);
end;

Но когда я пытаюсь скомпилировать, Delphi выдает мне эту ошибку:

[DCC Error] RPML.pas(57): E2029 Identifier expected but '^' found

Как я могу использовать указатель на параметризованныйвведите процедуру Delphi?Я не хочу делать весь класс шаблоном класса.

Ответы [ 2 ]

12 голосов
/ 17 марта 2011

Для этого вам нужно объявить тип указателя как вложенный тип в универсальном классе:

type 
  TMyGeneric<T> = class
  type
    P = ^T;
  public
    procedure DoStuff(tPtr: P);
  end;

И если вам нужен метод класса (т.е. не метод экземпляра), вы можете сделать это следующим образом:

type
  TMyGeneric<T> = record
  type
    P = ^T;
  public
    class procedure DoStuff(tPtr: P); static;
  end;

var
  int: Integer;
...
TMyGeneric<Integer>.DoStuff(@int);

Или используя параметр var:

type
  TMyGeneric<T> = record
  public
    class procedure DoStuff(var a: T); static;
  end;

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

Наконец, в Delphi не может быть универсального метода без создания универсального класса. Другими словами, нет аналога следующего кода шаблона C ++:

Ответ Торстена показывает, как реализовать универсальный метод без создания универсального класса, то есть аналога Delphi следующего кода шаблона C ++:

class C {
public:
   template <typename T>
   int SomeTemplateFunction(T* data) {
      printf("Address of parameter is %p\n", data);
      return 0;
   }
};

int a; 
char c; 
C cinst; 
cinst.SomeTemplateFunction<int>(&a); 
cinst.SomeTemplateFunction<char>(&c);

Ответ Торстена дает вам функцию класса, но в комментариях вы заявляете, что ищете обычную функцию-член.

type
  TMyClass = class
  public
    procedure DoStuff<T>(var a: T);
  end;

procedure TMyClass.DoStuff<T>(var a: T);
begin
end;

...
var
  instance: TMyClass;
  i: Integer;
  s: string;
...
  instance.DoStuff<Integer>(i);
  instance.DoStuff<string>(s);

Тем не менее, я борюсь с тем, как именно вы можете сделать что-то очень полезное в Delphi, что не может быть сделано так же эффективно без общего решения.

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

4 голосов
/ 18 марта 2011

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

type
  TMyGeneric = record
    class procedure DoStuff<T>(var aParam: T); static;
  end;

var
  int : Integer;
  s   : string;
...
TMyGeneric.DoStuff<Integer>(int);
TMyGeneric.DoStuff<string>(s);

РЕДАКТИРОВАТЬ: К сожалению, компилятор Delphi, похоже, не в состоянии выполнить типвывод при использовании параметров var, что делает необходимым явное указание универсального типа параметра с помощью <..> в вызовах методов.

Без «var» можно опустить <..> (но тогдаметод больше не может изменять переданную переменную).

...