Delphi中具有泛型类型的算术运算

让·米洛斯特·雷蒙德

我是Delphi的新手。对于我公司所需的项目,我需要将一些代码从现有C ++类转换为Delphi。其中一些类是模板,例如:

template <class T>
struct APoint
{
    T m_X;
    T m_Y;

    virtual void Add(T value);
};

template <class T>
void APoint<T>::Add(T value)
{
    m_X += value;
    m_Y += value;
}

我用它例如此代码

APoint<float> pt;
pt.m_X = 2.0f;
pt.m_Y = 4.0f;
pt.Add(5.0f);

而且效果很好。

现在,我需要为Delphi编写等效的代码。我试图根据上述C ++代码编写一个Delphi通用类:

APoint<T> = record
  m_X: T;
  m_Y: T;

  procedure Add(value: T);
end;

procedure APoint<T>.Add(value: T);
begin
  m_X := m_X + value;
  m_Y := m_Y + value;
end;

但是,此代码无法编译。我收到此错误:

E2015运算符不适用于此操作数类型

AFAIK该代码应该工作,我不明白它有什么问题。所以有人可以向我解释:

  1. 为什么这样的代码不能在Delphi中编译?

  2. 在Delphi中创建一个模板类的正确(最简单)的方法是什么,该模板类提供一个Add()函数,函数尽可能接近上述C ++代码和用法?

修改于17.10.2016

感谢所有的答复。因此,如果我理解正确,就无法创建类似c ++的样式模板,因为Delphi施加了c ++中不存在的几个约束。

基于此,我搜索了一种变通方法以达到我想要的目标。我发现以下解决方案:

IPoint<T> = interface
    procedure Add(value: T);
end;

APoint<T> = class(TInterfacedObject, IPoint<T>)
    m_X: T;
    m_Y: T;

    procedure Add(value: T); virtual; abstract;
end;

APointF = class(APoint<Single>)
    destructor Destroy; override;
    procedure Add(value: Single); reintroduce;
end;

destructor APointF.Destroy;
begin
    inherited Destroy;
end;

procedure APointF.Add(value: Single);
begin
    m_X := m_X + value;
    m_Y := m_Y + value;
end;

我用它例如此代码

procedure AddPoint;
var
    pt: IPoint<Single>;
begin
    pt := APointF.Create;

    APointF(pt).m_X := 2.0;
    APointF(pt).m_Y := 4.0;
    APointF(pt).Add(5.0);
end;

而且效果很好。但是我发现样式有点沉重,例如使用APointF(pt)的必要性。因此,关于上面的代码,我的问题是:

  1. 这个解决方案好吗?(即最好为我要支持的每种类型编写每个记录的版本,例如APointF,APointI,APointD等)
  2. 有没有一种方法可以简化此代码,例如,无需APointF(pt)转换即可直接调用pt.m_X的解决方案?注意,即使我认为这些属性比直接访问该变量更优雅,我还是在这里省略了属性的实现)
  3. 该解决方案的性能如何?(即,该解决方案比直接m_X:= m_X +附加值要慢得多吗?)

最后,我在Delphi代码中看到了另一个解决方案,可以通过这种方式实现2种泛型类型的相等比较:

function APoint<T>.IsEqual(const other: APoint<T>): Boolean;
var
    comparer: IEqualityComparer<T>;
begin
    Result := (comparer.Equals(m_X, other.m_X) and comparer.Equals(m_Y, other.m_Y));
end;

我试图阅读幕后的代码,但是发现它非常复杂。因此,我的问题是:

  1. 这样的解决方案是否比上述提议的解决方案更好?
  2. 是否有类似的现成的数学运算解决方案?
  3. 这样的解决方案的性能是否可以接受?

提前感谢您的回复

问候

戴维·赫弗南

Delphi泛型不支持对泛型类型起作用的算术运算符。为了使编译器接受代码,它需要知道对通用类型的每个操作在实例化时将可用。

通用约束允许您告诉编译器类型具有哪些功能。但是,通用约束不允许您告诉编译器该类型支持arithmetjc运算符。

不幸的是,您试图做的事根本不可能。当然,您可以自己构造框架,使用诸如接口之类的工具来执行算法,但是这样做会降低性能。如果可以接受,那么可以。否则,最好是硬着头皮避免在这里使用泛型。

哦,对于C ++模板。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

TypeScript泛型错误:算术运算的左侧必须为“ any”,“ number”,“ bigint”类型

具有可变类型参数的泛型

具有Kotlin的Dagger 2,在ApplicationComponent中返回具有泛型的类型

具有泛型的Scala类型类

在delphi中测试泛型的类型

在C#中检查T泛型类型具有属性S(泛型)

具有泛型的类,将其自身引用为Java中该泛型的类型

如何在流中定义具有指定类型的所有字段可选的泛型类型

具有withStyles的JSX元素中的泛型类型参数

具有通配符泛型类型的Lambda

Scala中具有泛型的结构类型

具有嵌套泛型类型的方法

具有相等运算符的打字稿泛型类型?

Swift中具有新泛型的泛型扩展

在TypeScript中,如何获取具有多个类型参数的方法中的泛型类型参数?

Typescript中具有泛型的子类型约束

在具有泛型类型的类中定义的数据类的类型提示

TypeScript泛型:React中具有联合类型的道具

具有接口类类型的泛型

为什么在具有可比约束的泛型函数中丢失泛型类型信息?

有什么方法可以在Delphi中动态转换泛型集合的项目类型?

具有泛型类型的泛型集合生成

类中具有2个泛型类型的方法,其中1个泛型类型

具有泛型类型的contains()

具有泛型类型的属性

具有泛型参数类型的函数

在 rust 中处理具有泛型和非泛型类型的枚举的返回

如何在所有能够进行算术运算的类型上实现泛型?

是否可以在 Delphi 中声明具有泛型值类型的 TDictionary?