简体   繁体   English

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

[英]How can I declare a pointer based on a generic type?

I have a class like this:我有一个这样的课程:

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

But when I try to compile, Delphi gives me this error:但是当我尝试编译时,Delphi 给了我这个错误:

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

How can I use a pointer to a parameterized type in a Delphi procedure?如何在 Delphi 过程中使用指向参数化类型的指针? I don't want to make the whole class a template class.我不想让整个班级成为模板班级。

To do this you need to declare a pointer type as a nested type in the generic class:为此,您需要在泛型类中将指针类型声明为嵌套类型:

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

And if you want a class method (ie not an instance method) you can do it this way:如果你想要一个类方法(即不是实例方法),你可以这样做:

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

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

Or using a var parameter:或者使用 var 参数:

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

It seems to be common to use records rather than classes for generic types that don't ever get instantiated.对于永远不会被实例化的泛型类型,使用记录而不是类似乎很常见。

Finally, you cannot have, in Delphi, a generic method without making the class generic. 最后,在 Delphi 中,如果不使类成为泛型,就不能拥有泛型方法。 In other words there is no analogue of the following C++ template code: 换句话说,没有以下 C++ 模板代码的类似物:

Thorsten's answer shows how to implement a generic method without making the class generic, that is the Delphi analogue of of the following C++ template code: Thorsten 的回答显示了如何在不使类泛型的情况下实现泛型方法,即以下 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);

Thorsten's answer gives you a class function but in the comments you state you are looking for a normal member function. 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);

However, what I'm struggling with is how exactly you could do anything very useful with this, in Delphi, that could not be done just as effectively without a generic solution.但是,我正在努力解决的是,在 Delphi 中,如果没有通用解决方案,就无法有效地完成任何非常有用的事情。

I'd appreciate any suggestions and would be happy to edit the answer to accommodate them.我很感激任何建议,并很乐意编辑答案以适应它们。

You can move the generic parameter from the class to the method, and use var instead of a pointer type:您可以将泛型参数从类移动到方法,并使用 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);

EDIT: Unfortunately the Delphi compiler doesn't seem to be able to perform type inference when var parameters are used which makes it necessary to explicitly specify the generic paramter type using <..> on the method calls.编辑:不幸的是,当使用 var 参数时,Delphi 编译器似乎无法执行类型推断,这使得必须在方法调用上使用 <..> 显式指定泛型参数类型。

Without the "var" the <..> can be omitted (but then the method can no longer modify the passed in variable).如果没有“var”,<..> 可以省略(但是该方法不能再修改传入的变量)。

type
  Pointer<T> = record
  public type
    Ty = ^T;
  end;

Now you can use this generic pointer anywhere现在你可以在任何地方使用这个通用指针

type A = class
    procedure<T> DoStuff(tPtr: Pointer<T>.Ty);
end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM