gpt4 book ai didi

delphi - 泛型类中的内部 const 似乎不是由编译器计算的

转载 作者:行者123 更新时间:2023-12-03 19:42:01 25 4
gpt4 key购买 nike

在 Delphi 中使用包含文件制作半通用容器有一个古老的技巧。

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=453&mode=print并从 3d 列表开始以掌握这个想法。

然而,在单元的 interface 中有两个相互依赖的 INC 文件和 implementation部分导致麻烦:似乎XE2将那些包含文件编译为独立单元,并且实现找不到接口(interface)中声明的函数。它不会每次都发生,但我未能确定条件,因此未能解决问题。

试图在 Delphi 泛型单元中以尽可能少的变化重新制定它(我不得不将巨大的遗留项目移至 XE2 并且“工作”应该是第一个,稍后进行优化和重构),我陷入了以下坑:

  TemplateList<_DATA_TYPE_> = class  
public
const MaxListSize = Maxint div (sizeof(Integer)*sizeof(_DATA_TYPE_));
type
TIntList = array[0..MaxListSize - 1] of _DATA_TYPE_;
PIntList = ^TIntList;
private
FList: PIntList;
FCount: Integer;

这给出了 TIntList 的下限错误。高于上限。我认为这意味着 const MaxListSize被评估为零,但 TIntType尝试立即评估,而不是在实际实例化类型时。

我想知道 XE3 或 XE4 是否解决了这个问题。如果有一种方法可以在 XE2 中编译而不需要进行重大的重新工作

PS。使数组 0..0 并抑制边界检查是通常的解决方案,但它会产生许多脆弱的未检查代码。也许我最终会使用真正的 TListTList<integer\>反而...

聚苯乙烯。有趣的事情,用复制粘贴重新形成内部类型
TIntList = array[0..Maxint div (sizeof(Integer)*sizeof(_DATA_TYPE_)) - 1] of _DATA_TYPE_;

将错误更改为“需要 const 表达式”。

因此,相同的表达式在编译器的一个分支中被认为是足够的,而在另一个分支中被认为是非常量的......我想知道它本身是否构成了一个不一致的错误。

最佳答案

编译器的问题似乎是在编译的通用阶段,sizeof(_DATA_TYPE_)不知道。因此编译器似乎使用了 0 的占位符值。 .当您实例化泛型类型时,sizeof(_DATA_TYPE_)被真实值替换。但为时已晚。数组类型边界检查在编译的通用阶段执行,此时 sizeof(_DATA_TYPE_)0所以编译器的噱头。

可以通过以下代码看出这种情况:

type
TemplateList<_DATA_TYPE_> = class
public
const
SizeOfDataType = sizeof(_DATA_TYPE_);
MaxListSize = Maxint div (sizeof(Integer)*SizeOfDataType);
end;

这会产生此编译器错误:
[dcc32 Error]: E2098 Division by zero

But, if you try this variant:

{$APPTYPE CONSOLE}

type
TemplateList<_DATA_TYPE_> = class
public
const
SizeOfDataType = sizeof(_DATA_TYPE_);
end;

begin
Writeln(TemplateList<Integer>.SizeOfDataType);
Writeln(TemplateList<Double>.SizeOfDataType);
Readln;
end.

输出是:
48

This shows that your constant declaration has a place holder value for the array type bounds checking, but has a true value once the generic has been instantiated. So, if the compiler postponed array type bounds checking until instantiation, then all would be well in terms of the compiler warning. But even then, the code would not do what you expect and desire. This program:

{$APPTYPE CONSOLE}

type
TemplateList<_DATA_TYPE_> = class
public
const
SizeOfDataType = sizeof(_DATA_TYPE_);
type
TMyArray = array [0..SizeOfDataType] of _DATA_TYPE_;
end;

begin
Writeln(high(TemplateList<Integer>.TMyArray));
Writeln(high(TemplateList<Double>.TMyArray));
Readln;
end.

产生一些不受欢迎的输出:
00

So it seems that not only are the array bounds checked at the generic phase of compilation, but the array bounds are fixed at that phase, and fixed using the place holder value of the type parameter size. What this means is that you cannot hope to achieve array bounds that vary based on the size of the data type.

The same behaviour is present in XE3, and I don't have XE4 at hand to check there.

I personally feel that this is a design flaw in the compiler that warrants a QC report.


In my opinion, the only viable way to resolve this is to give up trying to specify array bounds. I would declare it like this:

type
TemplateList<_DATA_TYPE_> = class
public
type
TIntList = array[0..0] of _DATA_TYPE_;
PIntList = ^TIntList;
private
FList: PIntList;
FCount: Integer;
end;

显然,您需要在本单元中禁用范围检查,但这并不是真正的困难,因为范围检查对原始代码没有任何帮助。

关于delphi - 泛型类中的内部 const 似乎不是由编译器计算的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17525874/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com