Delphi 如何基于泛型类型声明指针?

Delphi 如何基于泛型类型声明指针?,delphi,generics,pointers,parameters,delphi-2010,Delphi,Generics,Pointers,Parameters,Delphi 2010,我有一门课是这样的: type A = class procedure<T> DoStuff(tPtr: ^T); end; 如何在Delphi过程中使用指向参数化类型的指针?我不想使整个类成为模板类。为此,需要在泛型类中将指针类型声明为嵌套类型: type TMyGeneric<T> = class type P = ^T; public procedure DoStuff(tPtr: P); end; 类型 TMyGene

我有一门课是这样的:

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

如何在Delphi过程中使用指向参数化类型的指针?我不想使整个类成为模板类。

为此,需要在泛型类中将指针类型声明为嵌套类型:

type 
  TMyGeneric<T> = class
  type
    P = ^T;
  public
    procedure DoStuff(tPtr: P);
  end;
类型
TMyGeneric=类
类型
P=^T;
公众的
程序文件(tPtr:P);
结束;
如果您想要一个类方法(即不是实例方法),您可以这样做:

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

var
  int: Integer;
...
TMyGeneric<Integer>.DoStuff(@int);
类型
TMyGeneric=记录
类型
P=^T;
公众的
类程序文件(tPtr:P);静止的
结束;
变量
int:整数;
...
TMyGeneric.DoStuff(@int);
或者使用var参数:

type
  TMyGeneric<T> = record
  public
    class procedure DoStuff(var a: T); static;
  end;
类型
TMyGeneric=记录
公众的
等级程序DoStuff(变量a:T);静止的
结束;
对于从未实例化过的泛型类型,使用记录而不是类似乎很常见

最后,在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);
<索斯藤>的回答显示了如何在不使用类泛型的情况下实现泛型方法,即下面的C++模板代码的Delphi类比:

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);
C类{
公众:
模板
int SomeTemplateFunction(T*data){
printf(“参数地址为%p\n”,数据);
返回0;
}
};
INTA;
字符c;
C辛斯特;
cinst.SomeTemplateFunction(&a);
cinst.SomeTemplateFunction(&c);
Thorsten的答案为您提供了一个类函数,但在注释中您声明您正在寻找一个普通成员函数

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);
类型
TMyClass=类
公众的
程序DOSTUF(变量a:T);
结束;
程序TMyClass.DoStuff(变量a:T);
开始
结束;
...
变量
实例:TMyClass;
i:整数;
s:字符串;
...
例如:多斯塔夫(一);
例如:多斯塔夫;
然而,我正在努力解决的问题是,在Delphi中,如何使用它做任何非常有用的事情,如果没有一个通用的解决方案,就无法同样有效地完成


如果有任何建议,我将不胜感激,并很乐意编辑答案以适应它们。

您可以将泛型参数从类移动到方法,并使用var而不是指针类型:

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);
类型
TMyGeneric=记录
类程序DoStuff(var aParam:T);静止的
结束;
变量
int:整数;
s:字符串;
...
TMyGeneric.DoStuff(int);
TMyGeneric.DoStuff(s);
编辑:不幸的是,当使用var参数时,Delphi编译器似乎无法执行类型推断,这使得有必要显式指定在方法调用中使用的泛型参数类型

如果没有“var”,则可以省略(但是该方法不能再修改传入的变量)。

type
指针=记录
公共类型
Ty=^T;
结束;
现在,您可以在任何地方使用此通用指针

type A = class
    procedure<T> DoStuff(tPtr: Pointer<T>.Ty);
end;
类型A=类
程序DoStuff(tPtr:Pointer.Ty);
结束;

@David:你确定这是唯一的办法吗?我将函数设置为类函数的唯一原因是我可以使用泛型,我不想让类的用户为他想要使用函数的每种不同类型创建一个新的类实例。事实上,一个要求是用户可以在类的同一实例上使用具有不同类型参数的相同函数。如果这真的是唯一的方法,那就是Delphi的一个令人兴奋的局限性。@David我有另一个问题的例子,它不能是类方法。请在上面的评论中回答我的问题。@Hal我已经回答了。更新后的答案的第二个代码部分中永远不会有泛型类型的实例。您只需将其称为
MyGeneric.DoStuff(@int)有点罗嗦,但你就是这么做的。@David不,你误读了。我说过:事实上,一个要求是用户可以在同一个类实例上使用具有不同类型参数的相同函数。这意味着它们必须能够执行
mg.DoStuff(@int);mg.DoStuff(@pac)
@Hal,数组的元素总是连续的。阵列存储块的地址始终与阵列第一个元素的地址相同。尽管数组地址的语法可能因您拥有的数组类型而异,但获取第一个元素地址的语法始终相同,无论是开放数组、动态数组还是静态数组:
@a[Low(a)]
+1。我不知道你能做到这一点(显然!),但是,这对我来说并不合适。我认为您需要:
TMyGeneric.DoStuff(int)
。您是对的,需要使用“var”。我以前没有理由对var参数使用类型推断,并且错误地假设它与非var参数一样有效。显然,Delphi编译器在泛型方面的限制比我想象的还要多。如果你省略了“var”,类型推断是有效的,但我假设提问者询问指针是因为他打算修改传入的变量,因此省略var不是一个选项。我认为你应该编辑你的示例,使其编译,纠正最后一段,我想每个人都意识到Delphi编译器在泛型方面的局限性比他们今天想象的还要大。我还注意到,对于泛型(在RAD Studio 2010中),Intellisense很容易出错,并认为模板化方法不存在,但它编译得很好。
type A = class
    procedure<T> DoStuff(tPtr: Pointer<T>.Ty);
end;