【问题标题】:Is it a user error to declare a generic inline function `const` for shortstring, or is this a compiler bug?为短字符串声明通用内联函数“const”是用户错误,还是编译器错误?
【发布时间】:2016-05-03 08:34:04
【问题描述】:

编译器在使用函数时为shortstring生成了错误的代码

function TTestObject<T>.Compare(const Left, Right: T): integer; inline;

它会破坏参数。

下面的示例程序演示了这个概念:

program ShortStringsAndConst;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  TStr100 = string[100];

  TTestObject<T> = class
  private
    Bag1, Bag2: T;
    procedure RandomBags;
    procedure TestCompare;
    function CompareFail(const Left, Right: T): integer; inline;
    function CompareWin(const [ref] Left, Right: T): integer; inline;
  end;

var
  TestStr100: TTestObject<TStr100>;

  procedure Test;
  begin
    TestStr100:= TTestObject<TStr100>.Create;
    TestStr100.RandomBags;
    TestStr100.TestCompare;
  end;

{ TTestObject<T> }

procedure TTestObject<T>.RandomBags;
var
  a: integer;
begin
  PByteArray(@Bag1)^[0]:= SizeOf(T)- 1;
  for a:= 1 to SizeOf(T)- 1 do begin
    PByteArray(@Bag1)^[a]:= byte('a');
  end;
  Bag2:= Bag1;
end;

function TTestObject<T>.CompareFail(const Left, Right: T): integer;
var
  L,R: shortstring;
begin
  L:= PShortstring(@Left)^;
  R:= PShortstring(@Right)^;
  WriteLn(Format('Fail!! @Left = %p, @Right = %p, Left = %s, Right = %s',[@Left, @Right, L, R]));
end;

function TTestObject<T>.CompareWin(const [ref] Left, Right: T): integer;
var
  L,R: shortstring;
begin
  L:= PShortstring(@Left)^;
  R:= PShortstring(@Right)^;
  WriteLn(Format('Win:  @Left = %p, @Right = %p, Left = %s, Right = %s',[@Left, @Right, L, R]));
end;

procedure TTestObject<T>.TestCompare;
begin
  CompareFail(Bag1,Bag2);
  WriteLn;
  CompareWin(Bag1,Bag2);
  ReadLn;
end;

begin
  Test;
end.

问题
假设我可以在泛型函数中使用普通的const 是我的错误,还是这是一个编译器错误?

额外问题
除了 Shortstring,还有其他类型会导致 CompareFail 生成无效代码吗?

背景
我觉得没有强烈需要使用shortstring,但我正在编写一些通用库代码并且需要支持所有类型。

更新 这是一个编译器错误,已在 10.1 Berlin 中修复。

【问题讨论】:

  • 你为什么要使用[ref]。这只会导致代码变慢。
  • @DavidHeffernan 因为不使用[ref] 会导致代码无法正常工作:-(。不过我没有注意到速度上的差异,将仔细检查。
  • 声明为CompareFail(var Left, Right: T): integer; inline; 有效。
  • 哦,我明白了。这是一个错误。
  • @LURD,是的,除了你在长字符串上得到的 try-finally 和 ref-counting。所以这算不上胜利。

标签: delphi generics inline-code compiler-bug


【解决方案1】:

假设我可以在泛型函数中使用普通的 const 是我的错误,还是这是一个编译器错误?

假设你说的是真的,那么这是一个编译器错误。您需要报告错误并阻止使用短字符串。

【讨论】:

  • 报告归档:quality.embarcadero.com/browse/RSP-11385(如果您运行代码示例,您可以看到问题)。
  • 我可以声明短字符串的重载。这也解决了问题。
  • 而且它在 10.1 中是固定的。
猜你喜欢
  • 1970-01-01
  • 2020-03-08
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
  • 2014-08-09
  • 2012-04-08
  • 2012-03-18
  • 1970-01-01
相关资源
最近更新 更多