[fpc-pascal] Subclassing generic records?
Sven Barth
pascaldragon at googlemail.com
Thu Jul 20 12:11:34 CEST 2017
On 17.07.2017 19:20, Ryan Joseph wrote:
>
>> On Jul 17, 2017, at 10:58 AM, Sven Barth via fpc-pascal <fpc-pascal at lists.freepascal.org> wrote:
>>
>> I'll need to check whether Delphi allows that for helpers (doesn't matter whether the extended type is a specialization or not).
>>
>>
>
> Thanks Sven. Records/objects/classes in Pascal feel very confused right now. Records are moving in the direction of legacy style “objects” which are allocated on the stack so I wonder why objects just don’t replace records already? Having said that why don’t classes just replace records/objects except they allocate on the stack? These 3 distinct constructs don’t really make sense more imo.
First of records can't replace objects, because objects have inheritance
and a VMT for virtual methods not to mention destructors. Secondly this
would lead to all kind of backwards compatibility problems.
Classes are not designed to be allocated on the stack. They are only on
the heap, thus they are a different kind of beast to records and objects.
And records - unlike objects and classes - can have operator overloads
*inside* of them which allows this operators to be used inside generic
specializations.
I have also another solution for your original problem. Take this code:
=== code begin ===
program trechelpfld;
{$mode objfpc}
{$modeswitch advancedrecords}
type
TTest = record
x, y: Double;
end;
TTestHelper = record helper for TTest
private
function GetWidth: Double; inline;
function GetHeight: Double; inline;
procedure SetWidth(aValue: Double); inline;
procedure SetHeight(aValue: Double); inline;
public
property Width: Double read GetWidth write SetWidth;
property Height: Double read GetHeight write SetHeight;
end;
function TTestHelper.GetWidth: Double;
begin
Result := x;
end;
function TTestHelper.GetHeight: Double;
begin
Result := y;
end;
procedure TTestHelper.SetWidth(aValue: Double);
begin
x := aValue;
end;
procedure TTestHelper.SetHeight(aValue: Double);
begin
y := aValue;
end;
var
t: TTest;
x, y: Double;
begin
t.x := 42.0;
t.y := 21.0;
x := t.Width;
y := t.Height;
t.Width := y;
t.Height := x;
end.
=== code end ===
Through the use of "inline" this results in code without calls as the
assembly output of the main procedure without any optimizations shows:
=== code begin ===
.section .text.n_main
.balign 16,0x90
.globl PASCALMAIN
.type PASCALMAIN, at function
PASCALMAIN:
.globl main
.type main, at function
main:
.Lc21:
# Temps allocated between rbp-16 and rbp+0
# [45] begin
pushq %rbp
.Lc23:
.Lc24:
movq %rsp,%rbp
.Lc25:
leaq -16(%rsp),%rsp
call FPC_INITIALIZEUNITS
# [46] t.x := 42.0;
movq _$TRECHELPFLD$_Ld1,%rax
movq %rax,U_$P$TRECHELPFLD_$$_T
# [47] t.y := 21.0;
movq _$TRECHELPFLD$_Ld2,%rax
movq %rax,U_$P$TRECHELPFLD_$$_T+8
# [49] x := t.Width;
movsd U_$P$TRECHELPFLD_$$_T,%xmm0
movsd %xmm0,U_$P$TRECHELPFLD_$$_X
# [50] y := t.Height;
movsd U_$P$TRECHELPFLD_$$_T+8,%xmm0
movsd %xmm0,U_$P$TRECHELPFLD_$$_Y
# [52] t.Width := y;
movq U_$P$TRECHELPFLD_$$_Y,%rax
movq %rax,U_$P$TRECHELPFLD_$$_T
# [53] t.Height := x;
movq U_$P$TRECHELPFLD_$$_X,%rax
movq %rax,U_$P$TRECHELPFLD_$$_T+8
# [54] end.
call FPC_DO_EXIT
leave
ret
.Lc22:
.Le4:
.size main, .Le4 - main
=== code end ===
It might be more to write, but it works...
Regards,
Sven
More information about the fpc-pascal
mailing list