delphi 泛型类型指针

cclgggtu  于 2023-10-18  发布在  其他
关注(0)|答案(5)|浏览(123)

在将给定的高效的基于指针的哈希Map实现转换为通用哈希Map实现的过程中,我偶然发现了以下问题:
我有一个表示散列节点的类(散列Map实现使用二叉树)

THashNode <KEY_TYPE, VALUE_TYPE> = class
public
  Key      : KEY_TYPE;
  Value    : VALUE_TYPE;
  Left     : THashNode <KEY_TYPE, VALUE_TYPE>;
  Right    : THashNode <KEY_TYPE, VALUE_TYPE>;
end;

除此之外,还有一个函数应该返回指向哈希节点的指针。我想写

PHashNode = ^THashNode <KEY_TYPE, VALUE_TYPE>

但这不会编译(';"应为“,但找到”<")。
我怎么能有一个指向泛型类型的指针?
并对巴里凯利说:如果你读到这个:是的,这是基于您的哈希Map实现。您自己还没有编写过这样一个通用版本的实现,是吗?这会为我节省保存一些时间:)

h6my8fg2

h6my8fg21#

抱歉,粉碎机不支持指向开放泛型类型的指针,因为不支持泛型指针类型,尽管在某些情况下(编译器错误)可以创建它们(特别是指向泛型类型内部嵌套类型的指针);这个“特性”不能在更新中删除,以防我们破坏了某人的代码。对泛型指针类型的限制应该在未来被删除,但我不能保证什么时候。
如果有问题的类型是我写的JclStrHashMap(或古老的HashList单元)中的类型,那么,复制它的最简单方法是将节点类型更改为类,并通过适当的转换将任何双指针传递为Pointer。然而,如果我今天再写一遍那个单元,我不会把桶实现为二叉树。我有机会在Generics.Collections单元中编写字典,尽管在交付可靠的QA之前,所有其他 Delphi 编译器的工作时间都太紧了,并且泛型特性支持本身直到相当晚才发生变化。
我更愿意将哈希Map桶实现为双哈希、逐桶动态数组或来自连续数组的单元格链表中的一种,无论哪种都是使用代表性数据进行测试的最佳结果。其逻辑是,树/列表中的以下链接的缓存未命中成本应该支配树和列表之间的桶搜索中的任何差异,具有良好的哈希函数。当前的字典被实现为直接的线性探测,主要是因为它相对容易实现,并且可以使用可用的基本泛型操作集。
也就是说,二叉树桶应该是一个有效的对冲差散列函数;如果它们是平衡二叉树(=>甚至更多的修改成本),它们的平均性能为O(1),最坏情况为O(log n)。

guykilcj

guykilcj2#

要真正回答你的问题,你不能做一个指向泛型类型的指针,因为“泛型类型”不存在。你必须建立一个指向特定类型的指针,并填入类型参数。
不幸的是,编译器不喜欢在^后面找到尖括号。但它将接受以下内容:

TGeneric<T> = record
      value: T;
   end;

   TSpecific = TGeneric<string>;

   PGeneric = ^TSpecific;

但是“PGeneric = ^TGeneric<string>;“给出了一个编译器错误。听起来像是故障。如果我是你,我会向质检部报告。
你为什么要创建一个指向对象的指针呢? Delphi 对象是一种引用类型,所以它们已经是指针了。你只需要将对象引用转换为指针就可以了。

byqmnocz

byqmnocz3#

  • 如果 * Delphi 支持泛型指针类型,它应该看起来像这样:
type
  PHashNode<K, V> = ^THashNode<K, V>;

也就是说,在左侧声明类型名称的地方提到泛型参数,然后使用这些参数构造右侧的类型。
但是, Delphi **不支持这一点。请参见QC 66584
另一方面,我也质疑 * 拥有 * 指向类类型的指针的必要性。一般或不。他们只需要 * 非常 * 很少。

jmo0nnb3

jmo0nnb34#

在Generics.Collections单元中有一个名为TDictionary的通用哈希Map。不幸的是,它目前严重损坏,但显然将在更新#3中修复,这是由于within a matter of days, according to Nick Hodges

t9eec4r0

t9eec4r05#

你可以的尝试在泛型变量中声明指针类型。

TGenericArray<T> = record
 type
 PointerT = ^T;  // Declare your pointer type in here
 var
  Arr: Array of T;
  function Add(new_element: T; var myptr: PointerT) : Integer;
end;


function TGenericArray<T>.Add(new_element: T; var myptr: PointerT): Integer;
var len: Integer;
begin
len:=Length(Arr);
SetLength(Arr,len+1);
Result:=len;            // Function result is the index of array
myptr:=@Arr[len];       // Typed pointer of element
end;

并且你应该在源代码中使用正确的指针类型声明。看下面:

ElementPtr = ^T; // T: Same type in generic array, BUT THIS WILL NOT WORK!

ElementPtr = TGenericArray<T>.PointerT // This works perfectly.

祝你的代码好运

相关问题