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