在将给定的高效的基于指针的哈希图实现转换为通用哈希图实现的过程中,我偶然发现了以下问题:
我有一个代表哈希节点的类(哈希映射实现使用二叉树)
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>
但这不会编译(';'预期但'<' found).
如何获得指向泛型类型的指针?
致 Barry Kelly:如果您读到此内容:是的,这是基于您的哈希映射实现。您还没有自己编写过这样的通用版本的实现,是吗?这会节省我一些时间:)
对不起,粉碎者。不支持打开泛型类型的指针,因为不支持泛型指针类型,尽管在某些情况下可以(编译器错误)创建它们(特别是指向泛型类型内的嵌套类型的指针);如果我们破坏某人的代码,则无法在更新中删除此“功能”。对泛型指针类型的限制应该在将来被删除,但我不能做出承诺。
如果有问题的类型是我写的
JclStrHashMap
中的类型(或古老的 HashList
单元),那么,重现它的最简单方法是将节点类型更改为类并传递任何双精度类型指针为 Pointer
并进行适当的转换。但是,如果我今天再次编写该单元,我不会将存储桶实现为二叉树。我有机会在 Generics.Collections 单元中编写字典,尽管在交付可靠的 QA 之前,所有其他 Delphi 编译器的工作时间都太紧张,并且通用功能支持本身一直在变化,直到相当晚。
我更愿意将哈希映射存储桶实现为双哈希、每存储桶动态数组或来自连续数组的单元格链接列表之一,以使用代表性数据的测试中表现最好的为准。其逻辑是,在树/列表中跟踪链接的缓存未命中成本应该在具有良好哈希函数的树和列表之间的存储桶搜索中占主导地位。当前的字典被实现为直线探测,主要是因为它相对容易实现并且可以使用可用的原始通用操作集。
也就是说,二叉树桶应该是针对糟糕的哈希函数的有效对冲;如果它们是平衡二叉树(
=>
甚至更多的修改成本),它们的平均复杂度为 O(1),最坏情况下的性能为 O(log n)。
要真正回答您的问题,您不能创建指向泛型类型的指针,因为“泛型类型”不存在。您必须创建一个指向特定类型的指针,并填充类型参数。
不幸的是,编译器不喜欢在 ^ 之后查找尖括号。但它会接受以下内容:
TGeneric<T> = record
value: T;
end;
TSpecific = TGeneric<string>;
PGeneric = ^TSpecific;
但是“
PGeneric = ^TGeneric<string>;
”给出了编译器错误。对我来说听起来像是一个小故障。如果我是你,我会向 QC 报告这一点。
你为什么要尝试创建一个指向对象的指针? Delphi 对象是引用类型,因此它们已经是指针。您只需将对象引用转换为 Pointer 就可以了。
如果Delphi 支持通用指针类型,它必须看起来像这样:
type
PHashNode<K, V> = ^THashNode<K, V>;
也就是说,在左侧声明类型名称的地方提及泛型参数,然后使用这些参数来构造右侧的类型。
但是,Delphi 不支持这一点。请参阅QC 66584。
另一方面,我也质疑“拥有”指向类类型的指针的必要性。通用与否。仅非常很少需要它们。
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.
祝你的代码好运