【问题标题】:type inference based on generic argument type (Delphi)基于泛型参数类型的类型推断 (Delphi)
【发布时间】:2012-09-23 12:15:58
【问题描述】:

我正在尝试编写一个接受匹配参数类型的通用函数。
Delphi 确实在普通参数的简单情况下正确推断类型参数。

例如:

type
  TFoo = class
    function Pair<T>(e1, e2: T): TList<T>;
  end;

使用aFoo.Pair(1, 2); 调用它可以正常工作,但是当我将参数签名更改为泛型类型时

type
  TFoo = class
    function InsertInto<T>(aList: TList<T>; aVal: T): TList<T>;
  end;

并尝试调用它
aFoo.InsertInto(TList&lt;String&gt;.Create, 'bar');

然后编译器抱怨它:
E2010 Incompatible types: 'Generics.Collections.TList&lt;uTest.TFoo.InsertInto.T&gt;' and 'Generics.Collections.TList&lt;System.String&gt;'

我有什么办法可以编写这个(或类似的)方法,这样客户端就不必指定类型参数了吗?
aFoo.InsertInto&lt;String&gt;(TList&lt;String&gt;.Create, 'bar');

【问题讨论】:

  • 我认为错误消息给你一个线索,类型推断不会在这里完成工作。对于编译器的推理系统来说,这显然是比 Q 顶部的简单示例更难的问题。
  • 尝试将 aVal:T 设为第一个参数,也许这样会更容易编译,但机会非常非常小
  • 将“string”替换为“strign”,享受 E2010 不兼容的类型:'System.Generics.Collections.TList' 和 'Boolean'
  • 用 nil 替换第一个参数,你会得到 E2532 Couldn't infer generic type argument from different arguments types for method 'Pair' // 这可能是正确的错误,其他都是假的。我认为您可以打开有关误导性错误消息的 QC 票
  • 但是@Arioch,我们不知道来自第二个函数的消息是否真的具有误导性,因为我们还不了解编译器的问题。 first 函数的“无法推断泛型类型”错误无关紧要。对于第二个函数,编译器显然已经推断出类型(因为它没有抱怨它无法推断出它们),所以问题在于认识到推断出的类型与显式指定的类型相同——@ 987654327@ 等价于 System.String — 如果这确实是 T 被推断的那样。

标签: delphi generics delphi-xe type-inference


【解决方案1】:

我的猜测是因为 Delphi 的强类型特性。
uTest.TFoo.InsertInto.T 等同于 System.String 但它实际上是不同的类型

很像这个例子,Int1Int2 不是同一类型:

var
  Int1: array[1..10] of Integer;
  Int2: array[1..10] of Integer;
      ...
  Int1 := Int2; // <== BOOM! E2008 Incompatible types (in XE2)

实际问题不在于类型推断,而是类型不符合 Pascal/Delphi 的严格规则。

【讨论】:

  • 这听起来很合理。一个小小的吹毛求疵。您在谈论的是类型标识和兼容性,而不是强/弱类型系统。
  • 也可能是字符串文字'bar' 的类型不是System.String——至少现在还不是。字符串文字的类型相当流畅;编译器分配它需要的任何类型,至少当它知道它需要什么类型时。想一想如何将相同的字符串文字作为 UnicodeChar、PAnsiChar、WideString 或 ShortString 传递,所有这些都来自代码中的相同文本。所以可能uTest.TFoo.InsertInto.T实际上代表了六种不同的类型,编译器无法选择“最好的”一个。
  • 它也不适用于整数文字,尽管这可能有类似的原因(字节与整数与基数)。
  • @RobKennedy 你能用指针来解决这个问题吗?我在 Delphi7 中遇到过类似的问题,但这并不是真正的泛型(模板),这是通常的解决方案。
  • 我反对这个想法。原因一:“整数数组”——静态或动态——不兼容。但是所有的 TArray 都是一样的。并且有通用的 TList 所以它会遵循后一个特征,而不是前一个。原因二:我很高兴看到 type TFileName = type string; 制作孤立的字符串子类型。我个人认为这既有用又与 type X = type Y 背后的想法一致。但这不是 Delphi 处理字符串的方式。不管你做了什么类型声明,字符串总是分配兼容的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
  • 2023-04-01
相关资源
最近更新 更多