简体   繁体   English

指向泛型类型的指针

[英]Pointer to generic type

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. 并向Barry Kelly致敬:如果您读到这个:是的,这是基于您的哈希映射实现。 You haven't written such a generic version of your implementation yourself, have you? 你自己没有写过这样一个通用版本的实现,对吗? That would save me some time :) 那会节省我一些时间:)

Sorry, Smasher. 对不起,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. 如果有问题的类型是我编写的JclStrHashMap (或古老的HashList单元)中的类型,那么,重现它的最简单方法是将节点类型更改为类,并将任何双指针作为Pointer传递给适当的铸件。 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. 我有机会在Generics.Collections单元中编写字典,尽管所有其他Delphi编译器的工作时间都太紧,然后才能获得可靠的QA,并且通用功能支持本身也在不断变化。

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. 如果它们是平衡的二叉树( =>甚至更多的修改成本),它们将是平均O(1)和O(log n)最差情况下的性能。

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. 但是“ PGeneric = ^TGeneric<string>; ”给出了编译器错误。 Sounds like a glitch to me. 对我来说听起来像个小故障。 I'd report that over at QC if I was you. 如果我是你,我会在QC报告。

Why are you trying to make a pointer to an object, anyway? 无论如何,你为什么要尝试指向一个对象? Delphi objects are a reference type, so they're pointers already. Delphi对象是一种引用类型,因此它们已经是指针。 You can just cast your object reference to Pointer and you're good. 你可以将你的对象引用转换为Pointer,你很好。

If Delphi supported generic pointer types at all, it would have to look like this: 如果 Delphi支持通用指针类型,它必须如下所示:

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. 但是,Delphi 支持这一点。 See QC 66584 . 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. 他们只需要很少

There's a generic hash map called TDictionary in the Generics.Collections unit. 在Generics.Collections单元中有一个名为TDictionary的通用哈希映射。 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 . 不幸的是,它目前严重受损,但显然将在更新#3中修复,根据Nick Hodges的说法 ,该更新将在几天之内完成

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

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