This code doesn't compile (on Delphi 7 and Delphi XE2), and gives error message "E2036 Variable required". But if I change "object" to "record" then it compiles fine on Delphi XE2, since it has advanced records. I wanted to write portable code between Delphi versions, and use "object" on D7 and "record" on XE2 with IFDEFs, but it looks like impossibile in this case. Am I wrong, or this is a real compiler bug?
type
TD = String;
TC = object
public
V: String;
function D: TD;
end;
TB = object
public
V: String;
function C: TC;
end;
TA = object
public
V: String;
function B: TB;
end;
function TC.D: TD; begin end;
function TB.C: TC; begin end;
function TA.B: TB; begin end;
procedure Test;
var
A: TA;
s: string;
begin
s := A.V; // Ok
s := A.B.V; // Ok
s := A.B.C.V; // "E2036 Variable required", the cursor is between "C" and "."
end;
Thanks to everyone for the fast response. Surprisingly I found a workaround some minutes later. The "object" must have at leas one virtual method (and it's size must not be zero, so it must have a data field, but it don't have to be a managed type as "V: string" is). This ugly code compiles on Delphi 7 and also on Delphi XE2 if HAS_ADVANCEDRECORD is defined.
{.$define HAS_ADVANCEDRECORD}
type
TE = String;
TD = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
public
V: String;
function E: TE; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
end;
TC = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
public
V: String;
function D: TD; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
end;
TB = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
public
V: String;
function C: TC; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
end;
TA = {$ifdef HAS_ADVANCEDRECORD}record{$else}object{$endif}
public
V: String;
function B: TB; {$ifndef HAS_ADVANCEDRECORD}virtual;{$endif}
end;
function TD.E: TE; begin end;
function TC.D: TD; begin end;
function TB.C: TC; begin end;
function TA.B: TB; begin end;
procedure Test;
var
A: TA;
s: string;
begin
s := A.V; //* Ok
s := A.B.V; //* Ok
s := A.B.C.D.E; //* Solved: "E2036 Variable required"
end;
Actually I wanted to play with a fluent syntax sql query builder, and advanced records have an advantage over TObject. That is, they don't require lifetime management. A natural solution is using interfaces here, but I always got trouble with them.
I guess, it better worth to improve my knowledge on interfaces...
CodePudding user response:
This is a bug. You could submit a bug report, which would at least document it. However, I seriously doubt that Embarcadero will ever devote more resources to fixing it, and in any case that wouldn't help you with your older versions of Delphi.