program app;
{$mode objfpc}
{$modeswitch advancedrecords}
{$h+}
uses Generics.Collections;
type
generic GetClass<T: class> = class sealed
strict private type
TWrapperClass = class sealed(T)
_InstanceSize_: Boolean;
end;
public const
Size = UIntPtr(@TWrapperClass(nil)._InstanceSize_);
end;
generic TInplaceClass<T: class> = class(T)
private type
TSelf = specialize TInplaceClass<T>;
TSelfClass = class of TSelf;
strict private class threadvar
MemPointer: Pointer;
public
class function Inplace(mem: Pointer): TSelfClass; inline;
class function NewInstance: TObject; override;
procedure FreeInstance; override;
end;
generic TInlineClass<T: class> = record
strict private type
TWrapperClass = specialize TInplaceClass<T>;
strict private
space: array [0..specialize GetClass<T>.Size-1] of Byte;
public
instance: TWrapperClass;
function get: TWrapperClass.TSelfClass; inline;
end;
class function TInplaceClass.NewInstance: TObject;
begin
InitInstance(MemPointer);
NewInstance := TObject(MemPointer);
end;
class function TInplaceClass.Inplace(mem: Pointer): TSelfClass;
begin
MemPointer := mem;
Result := TSelf;
end;
procedure TInplaceClass.FreeInstance;
begin
end;
function TInlineClass.get: TWrapperClass.TSelfClass;
begin
instance := TWrapperClass(@space[0]);
Result := TWrapperClass.Inplace(@space[0]);
end;
var
m: specialize TDictionary<byte, byte>;
inplace_class: specialize TInlineClass<(specialize TDictionary<byte, byte>)>;
arr1: array [0..specialize GetClass<specialize TDictionary<byte, byte>>.Size-1] of byte;
arr2: array [0..1000] of byte;
begin
// ----
m := specialize TInplaceClass<(specialize TDictionary<byte, byte>)>.Inplace(@arr1[low(arr1)]).Create;
m.Capacity:=1024;
m.Add(1,2);
m.Add(3,4);
WriteLn(UIntPtr(@arr1[low(arr1)]));
WriteLn(UIntPtr(m));
WriteLn;
m.Free;
// ----
m := specialize TInplaceClass<(specialize TDictionary<byte, byte>)>.Inplace(@arr2[low(arr2)]).Create;
m.Capacity:=1024;
m.Add(1,2);
m.Add(3,4);
WriteLn(UIntPtr(@arr2[low(arr2)]));
WriteLn(UIntPtr(m));
WriteLn;
m.Free;
// ----
inplace_class.get.Create;
inplace_class.instance.Capacity:=1024;
inplace_class.instance.Add(1,2);
inplace_class.instance.Add(3,4);
WriteLn(UIntPtr(inplace_class.instance));
WriteLn(SizeOf(inplace_class));
WriteLn;
inplace_class.instance.Free;
ReadLn;
end.