指向泛型类型的指针

发布于 2021-11-28 06:17:43 字数 593 浏览 517 评论 4

在将给定的基于指针的高效哈希映射实现转换为通用哈希映射实现的过程中,我偶然发现了以下问题:

我有一个表示哈希节点的类(哈希映射实现使用二叉树)

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>

但没有编译(';' 预期但 '<' 找到)。

我怎样才能拥有指向泛型类型的指针?

致 Barry Kelly:如果您读到这篇文章:是的,这是基于您的哈希映射实现。 您还没有自己编写实现的通用版本,是吗? 那会节省我一些时间:)

In the process of transforming a given efficient pointer-based hash map implementation into a generic hash map implementation, I stumbled across the following problem:

I have a class representing a hash node (the hash map implementation uses a binary tree)

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;

In addition to that there is a function that should return a pointer to a hash node. I wanted to write

PHashNode = ^THashNode <KEY_TYPE, VALUE_TYPE>

but that doesn't compile (';' expected but '<' found).

How can I have a pointer to a generic type?

And adressed to Barry Kelly: if you read this: yes, this is based on your hash map implementation. You haven't written such a generic version of your implementation yourself, have you? That would save me some time :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

陌路黄昏 2022-06-07 23:01:45

在 Generics.Collections 单元中有一个称为 TDictionary 的通用哈希映射。 不幸的是,它目前严重损坏,但它显然会在更新 #3 中修复,该更新即将发布 根据 Nick Hodges 的说法,几天之内

There's a generic hash map called TDictionary in the Generics.Collections unit. Unfortunately, it's badly broken at the moment, but it's apparently going to be fixed in update #3, which is due out within a matter of days, according to Nick Hodges.

很酷不放纵 2022-06-07 23:01:44

如果Delphi 完全支持泛型指针类型,它必须看起来像这样:

type
  PHashNode<K, V> = ^THashNode<K, V>;

也就是说,在声明类型名称的左侧提及泛型参数,然后在构造右侧的类型。

但是,Delphi 支持这一点。 请参阅 QC 66584

另一方面,我也质疑一个指向类类型的指针的必要性。 通用与否。 只是非常很少需要它们。

If Delphi supported generic pointer types at all, it would have to look like this:

type
  PHashNode<K, V> = ^THashNode<K, V>;

That is, mention the generic parameters on the left side where you declare the name of the type, and then use those parameters in constructing the type on the right.

However, Delphi does not support that. See QC 66584.

On the other hand, I'd also question the necessity of having a pointer to a class type at all. Generic or not. they are needed only very rarely.

鸵鸟症 2022-06-07 23:01:41

要真正回答您的问题,您不能指向泛型类型,因为“泛型类型”不存在。 您必须创建一个指向特定类型的指针,并填充类型参数。

不幸的是,编译器不喜欢在 ^ 之后查找尖括号。 但它会接受以下内容:

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

   TSpecific = TGeneric<string>;

   PGeneric = ^TSpecific;

但是“PGeneric = ^TGeneric;”给出了编译器错误。 对我来说听起来像个小故障。 如果我是你,我会在 QC 报告这件事。

无论如何,你为什么要尝试指向一个对象? Delphi 对象是引用类型,所以它们已经是指针了。 您只需将对象引用转换为 Pointer 就可以了。

To actually answer your question, you can't make a pointer to a generic type, because "generic types" don't exist. You have to make a pointer to a specific type, with the type parameters filled in.

Unfortunately, the compiler doesn't like finding angle brackets after a ^. But it will accept the following:

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

   TSpecific = TGeneric<string>;

   PGeneric = ^TSpecific;

But "PGeneric = ^TGeneric<string>;" gives a compiler error. Sounds like a glitch to me. I'd report that over at QC if I was you.

Why are you trying to make a pointer to an object, anyway? Delphi objects are a reference type, so they're pointers already. You can just cast your object reference to Pointer and you're good.

熟人话多 2022-06-07 23:01:40

对不起,粉碎机。 不支持指向开放泛型类型的指针,因为不支持泛型指针类型,尽管在某些情况下可能(编译器错误)创建它们(特别是指向泛型类型内的嵌套类型的指针); 如果我们破坏了某人的代码,则无法在更新中删除此“功能”。 将来应该取消对通用指针类型的限制,但我不能保证什么时候。

如果所讨论的类型是我编写的 JclStrHashMap 中的类型(或古老的 HashList 单元),那么,重现它的最简单方法是将节点类型更改为成为一个类并通过适当的转换将任何双指针作为 Pointer 传递。 但是,如果我今天再次编写该单元,我不会将桶实现为二叉树。 我有机会在 Generics.Collections 单元中编写字典,尽管对于所有其他 Delphi 编译器来说,在交付可靠的 QA 之前工作时间太紧,并且通用功能支持本身一直在不断变化,直到相当晚。

我更愿意将哈希映射桶实现为双哈希、每桶动态数组或来自连续数组的单元格链接列表中的一种,以使用代表性数据的测试结果最好的为准。 其逻辑是,树/列表中后续链接的缓存未命中成本应该支配具有良好哈希函数的树和列表之间的桶搜索中的任何差异。 当前的字典被实现为直线探测,主要是因为它相对容易实现并且可以使用可用的原始通用操作集。

也就是说,二叉树桶应该是对付不良哈希函数的有效对冲; 如果它们是平衡二叉树(=> 甚至更多的修改成本),它们的平均 O(1) 和 O(log n) 最坏情况下的性能。

Sorry, Smasher. Pointers to open generic types are not supported because generic pointer types are not supported, although it is possible (compiler bug) to create them in certain circumstances (particularly pointers to nested types inside a generic type); this "feature" can't be removed in an update in case we break someone's code. The limitation on generic pointer types ought to be removed in the future, but I can't make promises when.

If the type in question is the one in JclStrHashMap I wrote (or the ancient HashList unit), well, the easiest way to reproduce it would be to change the node type to be a class and pass around any double-pointers as Pointer with appropriate casting. However, if I were writing that unit again today, I would not implement buckets as binary trees. I got the opportunity to write the dictionary in the Generics.Collections unit, though with all the other Delphi compiler work time was too tight before shipping for solid QA, and generic feature support itself was in flux until fairly late.

I would prefer to implement the hash map buckets as one of double-hashing, per-bucket dynamic arrays or linked lists of cells from a contiguous array, whichever came out best from tests using representative data. The logic is that cache miss cost of following links in tree/list ought to dominate any difference in bucket search between tree and list with a good hash function. The current dictionary is implemented as straight linear probing primarily because it was relatively easy to implement and worked with the available set of primitive generic operations.

That said, the binary tree buckets should have been an effective hedge against poor hash functions; if they were balanced binary trees (=> even more modification cost), they would be O(1) on average and O(log n) worst case performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文