Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2012-01

Generic type parameter variable initialization

8 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

kyan

Hello everybody.

I am new to FPC/Lazarus and I am trying to port some Delphi XE code that uses the units Generics.Defaults and Generics.Collections so I have to write these units for FPC because they do not exist and the code I am porting relies heavily on them. In this process I have come across various issues with Delphi/FPC generic compatibility but I have managed to overcome most of them.

In a method of a generic class I need to initialize a variable of type "T" (the generic class type parameter) with the type T's "default" value, which is 0 for ordinal types, '' for strings, nil for pointers/classes/interfaces, Unassigned for Variants etc. In Delphi there is the "compiler magic" function Default() and you can write:

procedure TMyClass<T>.SomeMethod;
var
  V: T;
begin
  ...
  V := Default(T);
  ...
end;
This does not compile in FPC. Is there an alternative in FPC for the
function Default()? I suppose one could do this:
procedure TMyClass<T>.SomeMethod;
var
  V: T;
begin
  ...
  Finalize(V);
  FillChar(V, SizeOf(V), 0);
  ...
end;

which is equivalent but it doesn't look too elegant. I am using FPC 2.7.1 for Win32/64.

Thank you in advance,

Constantine.

Sven Barth
to kyan
kyan wrote 8 lines
Hello everybody. I am new to FPC/Lazarus and I am trying to port some Delphi XE code that uses the units Generics.Defaults and Generics.Collections so I have to write these units for FPC because they do not exist and the code I am porting relies heavily on them. In this process I have come across various issues with Delphi/FPC generic compatibility but I have managed to overcome most of them.

If there are compatibility problems that are not yet mentioned in the bugtracker at http://bugs.freepascal.org/ it would be nice if you'd report them.

Show quoted text 18 lines
In a method of a generic class I need to initialize a variable of type "T" (the generic class type parameter) with the type T's "default" value, which is 0 for ordinal types, '' for strings, nil for pointers/classes/interfaces, Unassigned for Variants etc. In Delphi there is the "compiler magic" function Default() and you can write: procedure TMyClass<T>.SomeMethod; var V: T; begin ... V := Default(T); ... end; This does not compile in FPC. Is there an alternative in FPC for the function Default()? I suppose one could do this:

This functionality does not exist yet. See also here: http://bugs.freepascal.org/view.php?id=9420

Show quoted text 12 lines
procedure TMyClass<T>.SomeMethod; var V: T; begin ... Finalize(V); FillChar(V, SizeOf(V), 0); ... end; which is equivalent but it doesn't look too elegant. I am using FPC 2.7.1 for Win32/64.

For now you'll need to use this workaround solution.

Regards,
Sven

Florian Klämpfl
to Sven Barth
Sven Barth wrote 14 lines
> procedure TMyClass<T>.SomeMethod; > var > V: T; > begin > ... > Finalize(V); > FillChar(V, SizeOf(V), 0); > ... > end; > > which is equivalent but it doesn't look too elegant. I am using FPC > 2.7.1 for Win32/64. For now you'll need to use this workaround solution.

Has the workaround really the same effect? I really wonder why there is a need for default then ...

Sven Barth
to Florian Klämpfl
Florian Klämpfl wrote 18 lines
Am 05.01.2012 14:19, schrieb Sven Barth: >> procedure TMyClass<T>.SomeMethod; >> var >> V: T; >> begin >> ... >> Finalize(V); >> FillChar(V, SizeOf(V), 0); >> ... >> end; >> >> which is equivalent but it doesn't look too elegant. I am using FPC >> 2.7.1 for Win32/64. > > For now you'll need to use this workaround solution. Has the workaround really the same effect? I really wonder why there is a need for default then ...

It should at least be sufficent for the most common cases:
* ordinals
* strings
* classes
* records (and objects)

I don't know about Variants though. The Delphi help isn't helping either ;)

Regards,
Sven

kyan
to Florian Klämpfl: Has the workaround really the same effect? I really wonder why there is a need for…
Florian Klämpfl wrote
Am 05.01.2012 14:19, schrieb Sven Barth: Has the workaround really the same effect? I really wonder why there is a need for default then ...

Yes, works for Variants as well. Look at the implementation of System._FinalizeArray() in Delphi; it handles tkVariant type kind. Come to think of it, it can be elegantly wrapped up in the following generic class:

type
 TDefault<T> = class
   class function Value: T; inline;
 end;
class function TDefault<T>.Value: T;
begin
 Finalize(Result);
 FillChar(Result, SizeOf(Result), 0);
end;

and used like this:

type
  TSomeRec = record
    S: string;
    V: Variant;
    I: Integer;
  end;
var
 S: string;
 I: Integer;
 V: Variant;
 X: IInterface;
 C: TObject;
 D: TDateTime;
 R: TSomeRec;
 P: Pointer;
begin
 S := 'test';
 I := 42;
 V := Date;
 D := Date;
 X := Self;
 C := Self;
 R.S := 'test1';
 R.V := Date;
 R.I := 99;
 P := Self;
 S := TDefault<string>.Value;
 I := TDefault<Integer>.Value;
 V := TDefault<Variant>.Value;
 D := TDefault<TDateTime>.Value;
 X := TDefault<IInterface>.Value;
 C := TDefault<TObject>.Value;
 R := TDefault<TSomeRec>.Value;
 P := TDefault<Pointer>.Value;
end;
Sven Barth
to kyan
kyan wrote 7 lines
On Thu, Jan 5, 2012 at 4:03 PM, Florian Klämpfl wrote: > Am 05.01.2012 14:19, schrieb Sven Barth: > Has the workaround really the same effect? I really wonder why there is > a need for default then ... Yes, works for Variants as well. Look at the implementation of System._FinalizeArray() in Delphi; it handles tkVariant type kind.

Saying a FPC compiler developer to look at the Delphi implementation is problematic, because than we could get accused of copying code (which is why I use the Delphi XE starter version which does not contain the source code of the RTL and VCL).

Come to think of it, it can be elegantly wrapped up in the following generic class:

While this does indeed look nicely it's still not Delphi compatible ;)

Regards,
Sven

kyan
to Sven Barth
Saying a FPC compiler developer to look at the Delphi implementation is problematic, because than we could get accused of copying code (which is why I use the Delphi XE starter version which does not contain the source code of the RTL and VCL).

I am sorry, I wasn't aware of that. But by means of testing I found that Finalize() works correctly for Variants in Lazarus as well. I don't know about the internals much but I suppose the place to look in FPC is procedure fpc_finalize() in objpas.inc which does handle tkVariant as well.

While this does indeed look nicely it's still not Delphi compatible ;)

I think it is, it works in my Delphi XE exactly the way it does in Lazarus. It is just not defined in Delphi's RTL. I meant it as a temp solution until you implement Default() or something equivalent.

Anyway, let me not waste any more of your time. :)

Regards.

Sven Barth
to kyan
kyan wrote 10 lines
> Saying a FPC compiler developer to look at the Delphi implementation is > problematic, because than we could get accused of copying code (which is why > I use the Delphi XE starter version which does not contain the source code > of the RTL and VCL). I am sorry, I wasn't aware of that. But by means of testing I found that Finalize() works correctly for Variants in Lazarus as well. I don't know about the internals much but I suppose the place to look in FPC is procedure fpc_finalize() in objpas.inc which does handle tkVariant as well.

Hmm... the implementation of Default might not be that hard in the end... if I find the time I might experiment with an implementation at the weekend.

Show quoted text 5 lines
> While this does indeed look nicely it's still not Delphi compatible ;) I think it is, it works in my Delphi XE exactly the way it does in Lazarus. It is just not defined in Delphi's RTL. I meant it as a temp solution until you implement Default() or something equivalent.

My sentence was meant like this: It looks nice and works in FPC and Delphi, but it can not be used the same as Default. ;)

Regards,
Sven