本文介绍了Delphi中具有泛型类型的算术运算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new in Delphi. For a project required by my company, I need to translate some code from our existing C++ classes to Delphi. Some of these classes are templates, such as:

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;
}

例如,我使用它用此代码

I use it e.g. with this code

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

这很好用.

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

Now I need to write equivalent code for Delphi. I tried to write a Delphi Generic class, based on the C++ code above:

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;

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

However this code does not compile. I get this error:

AFAIK该代码应该可以正常工作,我不明白它有什么问题.任何人都可以向我解释:

AFAIK this code should work, and I don't understand what is wrong with it. So can anybody explain to me:

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

  1. Why a such code does not compile in Delphi?

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

What is the correct (and simplest) way in Delphi to create a template class that provides an Add() function, as closest as possible to the C++ code and usage above?

编辑于2016年10月17日

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

Thanks for all the replies. So if I understood correctly, there is no way to create a c++-like style template, because Delphi imposes several constraints that not exists in c++.

基于此,我搜索了一种解决方法以实现我想要的目标.我找到了以下解决方案:

Based on that, I searched a workaround to reach the objective I want. I found the following solution:

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;

例如,我使用它用此代码

I use it e.g. with this code

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)的必要性.因此,关于上面的代码,我的问题是:

and this works well. However I find the style a little heavy, e.g. the necessity to use APointF(pt). So, in relation to code above, my questions are:

  1. 此解决方案是一个好的解决方案吗? (即,最好为我要支持的每种类型编写每条记录的版本,例如APointF,APointI,APointD等)
  2. 是否有一种方法可以简化此代码,例如一个无需APointF(pt)转换即可直接调用pt.m_X的解决方案? (注意,这里我省略了属性的实现,即使我认为它们比直接访问变量更优雅)
  3. 该解决方案的性能如何? (即,该解决方案比直接m_X:= m_X +附加值要慢得多吗?)
  1. Is this solution a good solution? (i.e. better to write a version of each record for each type I want to support, like e.g APointF, APointI, APointD, ...)
  2. Is there a way to simplify this code, e.g. a solution to call pt.m_X directly without the APointF(pt) conversion? (NOTE I omitted here the implementation of properties, even if I think them more elegant than accessing the variable directly)
  3. What about the performances of this solution? (I.e. is this solution drastically slower than a direct m_X := m_X + value addition?)

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

Finally, I saw another solution in the Delphi code, where it is possible to implement an equality comparison of 2 generic types this way:

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;

我试图阅读幕后的代码,但是我发现它非常复杂.所以,我的问题是:

I tried to read the code behind the scene, however I found it terribly complicated. So, my questions are:

  1. 这样的解决方案比上面提出的解决方案好吗?
  2. 对于数学运算是否有类似的即用型解决方案?
  3. 这样的解决方案的性能可接受吗?

提前感谢您的回复

致谢

推荐答案

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

Delphi generics do not support arithmetic operators that act on generic types. In order for the compiler to accept the code it needs to know that each operation on a generic type is going to be available upon instantiation.

通用约束使您可以告诉编译器该类型具有的功能.但是,通用约束不允许您告诉编译器该类型支持arithmetjc运算符.

Generic constraints allow you to tell the compiler what capabilities the type has. However generic constraints do not allow you to tell the compiler that the type supports arithmetjc operators.

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

Unfortunately what you are trying to do is simply not possible. For sure you can construct frameworks yourself that can use tools like interfaces to get the arithmetic performed but doing so gives up performance. If that is acceptable then fine. Otherwise you are best biting the bullet and avoiding generics here.

哦,对于C ++模板.

Oh for C++ templates.

这篇关于Delphi中具有泛型类型的算术运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-27 16:13