On 2/22/23 15:11, Sven Barth wrote:
Kostas Michalopoulos via fpc-devel <fpc-devel@lists.freepascal.org
<mailto:fpc-devel@lists.freepascal.org>> schrieb am Mi., 22. Feb. 2023,
10:37:
> Because Delphi doesn't have them and when constraints were
implemented
> they were implemented for Delphi compatibility.
Can they be added? The original announcement ~13 years ago mentioned
that those could be added at some point. "object" and "operator X"
would
be quite useful for me.
Some additional constraints might be added. However I have none of them
planned currently and enough other things to do.
I tried to use constraints at some point in my code but they proven too
limited in functionality - the biggest issue i faced was that i
couldn't
use a specialization with a forward declared class (which is the entire
point of the forward declaration). For example i have a generic
collection that only works on TSerializable subclasses so i gave it
that
constraint, but in another unit i need to define a specialization
for it
before it was defined (so the class was available with a forward class
declaration) since that specialization also needs to be used by the
class itself. In general it seems like having constrained generic work
with a tree structure of derived types that use the generic itself is
impossible.
Wouldn't storing a list of "specializations to confirm later in this
unit" work (with later being when the class is actually defined in the
unit)? The language already has forward declarations for a bunch of
other things.
Forward declarations can not be used for constraints, because a
specialization of the generic might be used before the forward declared
type is fully defined and the compiler *must* be able to check whether
the parameter in question is compatible at the time the specialization
is declared.
Regards,
Sven
That is what the compiler does now, but can't it be changed to treat
constraints that use forward declarations as unconstrained (at least as
far as these forward declarations are concerned) until the moment they
are declared and validate those constraints at that point?
After all the code below does work if there is no constraint despite the
specialization being used before the forward declaration:
----
program Test;
{$MODE OBJFPC}{$H+}
type
TProvidesFoo = class
function Foo: Integer; virtual; abstract;
end;
// The following with a constraint could be instead:
// generic TGetFoo<T: TProvidesFoo> = class
generic TGetFoo<T> = class
Wrap: T;
function GetFoo: Integer;
end;
type
TForwardClass = class;
// Instead of making the test here, add it to a list to check later...
TFCHasFoo = specialize TGetFoo<TForwardClass>;
procedure DumpFoo(FCHasFoo: TFCHasFoo);
begin
Writeln(FCHasFoo.GetFoo);
end;
function TGetFoo.GetFoo: Integer;
begin
Result:=Wrap.Foo;
end;
type
// ...and when this is declared check the if any of the remaining
// checks in the list will be valid or not and remove it from the list
TForwardClass = class(TProvidesFoo)
function Foo: Integer; override;
end;
function TForwardClass.Foo: Integer;
begin
Result:=42;
end;
var
FC: TForwardClass;
HF: TFCHasFoo;
begin
HF:=TFCHasFoo.Create;
HF.Wrap:=TForwardClass.Create;
DumpFoo(HF);
HF.Wrap.Free;
HF.Free;
end.
----
At the end of the day this isn't a major flaw, after all if the expected
functionality wasn't there (e.g. the generic code tried to access
something the type used in the specialization didn't provide) you'd
still get a compile error anyway, though it does feel a bit like there a
hole in Free Pascal's type safety here (e.g. imagine passing a type to a
specialization that happens to have the same function call so the code
compiles but the call does something different than what you'd expect).
Kostas
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel