Search code examples
constantsdelphi-7delphi-11-alexandria

Delphi 11: Constant object cannot be passed as var parameter


I am trying to transfer my Delphi 7 code to Delphi 11.

The following code worked fine in Delphi 7, but in Delphi 11 I get a compile-time error

[dcc32 Error] VELOS.PAS(44): E2197 Constant object cannot be passed as var parameter

Is there a way to make Delphi 11 compile my code?

I can make the initialized constants be global initialized var, but changing all similar code to comply with Delphi 11 is a lot of work because I use similar stuff a lot.

My code:

function Kt_f25(Mrd,Md,aro,dh:real; var k:real):real;
const
  vmax=9;
type
  Atype=array [1..vmax] of real;
const
  arA:Atype=(    10,  15,  20,  25,  30,  40,  60, 100, 200);

  v0a08:  Atype=( 235, 170, 135, 115, 100,  82,  63,  46,  33);
  v1a08:  Atype=( 135, 102,  84,  74,  67,  57,  47,  37,  30);

  v0a09:  Atype=( 166, 118,  95,  80,  70,  57,  44,  33,  23);
  v1a09:  Atype=(  99,  76,  63,  56,  50,  43,  36,  29,  22);

  v0a10:  Atype=( 120,  86,  70,  59,  51,  42,  32,  24,  17);
  v1a10:  Atype=(  77,  59,  50,  44,  40,  34,  28,  22,  16);

  dhA:array [1..3] of real=(8,9,10);
var
  v0,v1,v2,kt:real;
  res:array [1..3] of real;    
begin
  if Md>0 then k:=Mrd/Md else if Mrd=0 then k:=1 else k:=10;
  if k>1.3 then k:=1.3;
  if k<0 then k:=0;

  v0:=LinearApr(arA,v0a08,aro*1000,vmax); v1:=LinearApr(arA,v1a08,aro*1000,vmax); v2:=20;
  if k>=1 then res[1]:=v2+k*(v1-v2)/0.2 else res[1]:=v1+k*(v0-v1)/1.0;

  v0:=LinearApr(arA,v0a09,aro*1000,vmax); v1:=LinearApr(arA,v1a09,aro*1000,vmax); v2:=20;
  if k>=1 then res[2]:=v2+k*(v1-v2)/0.2 else res[2]:=v1+k*(v0-v1)/1.0;

  v0:=LinearApr(arA,v0a10,aro*1000,vmax); v1:=LinearApr(arA,v1a10,aro*1000,vmax); v2:=20;
  if k>=1 then res[3]:=v2+k*(v1-v2)/0.2 else res[3]:=v1+k*(v0-v1)/1.0;

  kt:=LinearApr(dhA,res,dh*10,3);

  Result:=kt/10;
end;

function LinearApr(var ap1,AV1; r:real; Vmax:integer):real;
const gmax=100;                                                          
type
  Atype=array [1..gmax] of real;
var
  i,j:integer;
  ap2:Atype absolute ap1;
  AV2:Atype absolute AV1;
  ap,AV:Atype;
begin
...
end;

Solution

  • The error is self-explanatory. You are passing typed constants where variable references are expected.

    You are encountering the following change in behavior between Delphi 7 and 11:

    Writeable typed constants (Delphi)

    The $J directive controls whether typed constants can be modified or not. In the {$J+} state, typed constants can be modified, and are in essence initialized variables. In the {$J-} state, typed constants are truly constant, and any attempt to modify a typed constant causes the compiler to report an error.

    ...

    In early versions of Delphi and Object Pascal, typed constants were always writeable, corresponding to the {$J+} state. Old source code that uses writeable typed constants must be compiled in the {$J+} state, but for new applications it is recommended that you use initialized variables and compile your code in the {$J-} state.

    The default state is {$J-} in modern Delphi versions. So, simply add an explicit {$J+} or {$WRITEABLECONST ON} directive to your existing code to get the old behavior.