Hi Sven,
It's not that simple. In principle you're right that the compiler
could try to merge more implementations, but this does not depend on
the declaration of the generic, but the use of the parameter types.
I mostly use generics for containers, especially hashmaps. They only
stores the values and never calls specific methods on them
Not to mention that your TBaseHashMap would not work with managed types...
That would need be handled separately. There are probably also people
who want a container that calls .free on TObject descendants.
Best,
Benito
On 26.04.20 14:18, Sven Barth wrote:
Am 26.04.2020 um 14:01 schrieb Benito van der Zander:
Hi,
perhaps it could be used to merge specializations (if fpc cannot do
that on its own):
Like when you have a hashmap THashMap<Key,Value>, and need three
specializations:
THashMap<string, pointer>
THashMap<string, TObject>
THashMap<string, sizeint>
It is basically three times the same hashmap, but if fpc does not
detect that, it might generate three times the same assembly code,
which waste a lot of space.
But with constants it can be merged to TBaseHashMap<Key, ValueSize:
integer> and then you only have one map in the assembly code, and
three wrappers to remove the casting:
THashMap<string, pointer> = TBaseHashMap<string, sizeof(pointer) > =
TBaseHashMap<string, 8 >
THashMap<string, TObject> = TBaseHashMap<string, sizeof(TObject) > =
TBaseHashMap<string, 8 >
THashMap<string, sizeint> = TBaseHashMap<string, sizeof(sizeint) > =
TBaseHashMap<string, 8 >
It's not that simple. In principle you're right that the compiler
could try to merge more implementations, but this does not depend on
the declaration of the generic, but the use of the parameter types.
Take the following example:
=== code begin ===
{$mode objfpc}
type
generic TTest<T> = class
procedure DoSomething;
end;
TMyClass1 = class
procedure Foobar;
end;
TMyClass2 = class
procedure Foobar; virtual;
end;
procedure TTest.DoSomething;
var
o: T;
begin
o.Foobar;
end;
procedure TMyClass1.Foobar;
begin
Writeln('TMyClass1.Foobar');
end;
procedure TMyClass2.Foobar;
begin
Writeln('TMyClass2.Foobar');
end;
type
TTestMyClass1 = specialize TTest<TMyClass1>;
TTestMyClass2 = specialize TTest<TMyClass2>;
begin
end.
=== code end ===
In case of TMyClass1 this will result in a static call to
TMyClass1.Foobar, however in case of TMyClass2 this will result in an
indirect call through the VMT.
The type information needs to be correct as well, even more so once we
have support for Extended RTTI where one can enumerate non-published
fields, properties and methods in addition to published.
Not to mention that your TBaseHashMap would not work with managed types...
Regards,
Sven
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel