[fpc-devel] How FPC handles dynamic arrays with const modifier?
Maciej Izak
hnb.code at gmail.com
Tue Aug 13 14:41:54 CEST 2013
> I don't see a reason to use hacks for such code.
>
It is hard to explain. You will see it soon in all its glory ;). It's very
important construction (I use this construction very often - generics,
serialization, script languages binding...). A short introduction:
===begin code===
// I need universal non generic method to compare arrays without knowledge
of its TypeInfo...
class function TEquals.DynArray(constref ALeft, ARight: Pointer): Boolean;
var
_self: TAbstractHashCode.PSpoofInterfacedTypeSizeObject absolute Self; //
few more tricks...
LLength: Integer;
begin
LLength := DynArraySize(ALeft);
if LLength <> DynArraySize(ARight) then
Exit(False);
Result := CompareMem(ALeft, ARight, LLength * _self.Size);
end;
===end code===
you wrote earlier in my other topic:
"You can't do things as equality tests in a general way anyway (best
example: case sensitive vs. case insensitive comparison of strings)."
So... I just finished writing something theoretically impossible to write
O_o. Now I do equality tests in a general way (partially because the
construction like in Foo).
To get:
===begin code===
IEqualityComparer<T> = interface
function Equals(constref ALeft, ARight: T): Boolean;
function GetHashCode(constref AValue: T): UInt32; overload;
function GetHashCode(constref AValue: T; out APrimaryHash: UInt32):
UInt32; overload; // for double hashing
end;
===end code===
for any type (seriously any type supported by FPC except file type - Error:
File types must be var parameters), just call TEqualityComparer<T>.Default:
===begin code===
var
ec_array: IEqualityComparer<TIntegerDynArray>;
ec_string: IEqualityComparer<string>;
begin
ec_array := TEqualityComparer<TIntegerDynArray>.Default;
ec_array :=
TEqualityComparer<TIntegerDynArray>.Default(TOptionalNonDefaultHashFactory);
// case insensitive comparer
ec_string :=
TEqualityComparer<string>.Construct(MyNonCaseSensitiveComparerMethod);
// or soon with anonymous methods
ec_string := TEqualityComparer<string>.Construct(
function(constref ALeft, ARight: string): Integer);
begin
Result := SameText(ALeft, ARight);
end, TOptionalNonDefaultHashFactory);
===end code===
At this moment you can use dictionary (with any custom IEqualityComparer)
in FPC with any type (used type don't need to implement any additional
operators):
===begin code===
var
dr: TDictionary<TMyRecord, string>;
dp: TDictionary<PAnyPointer, Variant>;
dcr: TDictionary<TClass, TArrayOfObjects>;
da: TDictionary<TIntegerDynArray, Single>;
dCaseInsensitive: TDictionary<string, TObject>;
dCaseSensitive: TDictionary<string, TObject>;
{... and so on...}
dCaseInsensitive := TDictionary<string, TObject>(StringC
aseInsensitiveEqualityComparer);
dCaseSensitive := TDictionary<string, TObject>.Create; // default case
sensitive
===end code===
If you need to use default freepascal operators for comparisons there is
also TFastDictionary - for some optimizations.
Btw. I proposed the creation of the new system functions: GetReferenceToValue
and GetValueSize (I think it's still a good idea). This would simplify some
things...
> I wonder why this combination compiles at all O.o
>
comfortable for my tricks ^_^
Regards,
HNB
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20130813/bd0da09d/attachment.html>
More information about the fpc-devel
mailing list