Nested constants of nested structured types are unsupported?

余生颓废 提交于 2019-12-29 07:46:10

问题


Despite of what Delphi reference says

structured types can contain other structured types; a type can have unlimited levels of structuring

with notable exception what structured typed constants

cannot contain file-type values at any level

I discovered what I cannot use record constant as an element of array constant of the same type.

Testcase

type
  MyRecord = record MyField: Integer end;

const
  Typical: array[0..1] of MyRecord = ((MyField: 0), (MyField: 1));

  { now I tried to achieve more clarity by declaring a specific constant }
  Zero: MyRecord = (MyField: 0);

  { and compiler refused to accept that }
  Bad: array[0..1] of MyRecord = (Zero, (MyField: 1));  { E2029 '(' expected but identifier 'Zero' found }

I tested this code with several Borland compilers, all of them exhibited the same behaviour. UPD: also the same for FPC, but not for GPC(!).

Question(s)

What is going on here? Am I correct with "Nested constants of nested structured types are unsupported" conclusion in the question title? Any more analysis of an issue?


回答1:


It appears that this isn't possible, the underlying cause is that ZeroRec isn't truly a constant, it is more like an initialised static variable.

If {$WRITEABLECONST ON} is specified, then it can be trivially changed. Even with $WRITEABLECONST OFF, it can be changed by some creative type casting (tested in XE2):

program Project3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
  MyRecord = record MyField: Integer end;
  PMyRecord = ^MyRecord;

const
  Typical: array[0..1] of MyRecord = ((MyField: 0), (MyField: 1));

  { now I tried to achieve more clarity by declaring a specific constant }
  ZeroRec: MyRecord = (MyField: 0);
  { and compiler refused to accept that }
//  Bad: array[0..1] of MyRecord = ((MyField: Zero), (MyField: 1));  { E2029 '(' expected but identifier 'Zero' found }
begin
  try
    { TODO -oUser -cConsole Main : Insert code here }
    WriteLn(ZeroRec.MyField);
    PMyRecord(@ZeroRec)^.MyField := 2;
    WriteLn(ZeroRec.MyField);
    readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

This will output

0

2

The behaviour is also evident with simple types,

  Zero = 0;
  ZeroRec: MyRecord = (MyField: Zero);

compiles as expected, however

  Zero : Integer = 0;
  ZeroRec: MyRecord = (MyField: Zero);

gives [DCC Error] Project3.dpr(19): E2026 Constant expression expected




回答2:


What you are declaring is called a Typed Constant. And in this specific case it is an Array Constant. The documentation states (emphasis mine):

To declare an array constant, enclose the values of the array's elements, separated by commas, in parentheses at the end of the declaration. These values must be represented by constant expressions.

The code that the compiler objects to is where you attempt to use a typed constant where only a constant expression is allowed.

This is one of the most frustrating areas of the Delphi language because the language forces you to repeat yourself.



来源:https://stackoverflow.com/questions/16247819/nested-constants-of-nested-structured-types-are-unsupported

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!