It was pointed out in the comments to my previous post that my simple generic sorting routine contains additional overhead compared to TArray Rtl code (Generic.Collections & Generic.Defaults units) because RTTI is used inside the loop. Yes, that is true. Let us improve the code by taking RTTI check away from the loop, while keeping the code simple (without using over-weighted and tricky IComparer interface).
Simple tasks should have simple solutions. Now when I look at it the solution seems quite obvious, still I spent some hours trying to find it – generics are weird for beginner. The last step that led to working code was to declare generic procedural type TCompare inside generic class TArray, without it the code would not compile:
unit GenericSort; interface type TArray<T> = class public type TCompare = function(const L, R: T): Integer; private class procedure InternalSort(var A: array of T; Compare: TCompare); static; public class procedure InsertionSort(var A: array of T); static; end; function CompareInt(const L, R: Integer): Integer; implementation uses SysUtils, TypInfo; class procedure TArray.InternalSort(var A: array of T; Compare: TCompare); var I, J: Integer; Item: T; P: PTypeInfo; begin for I:= 1 + Low(A) to High(A) do begin Item:= A[I]; J:= I - 1; while (J >= Low(A)) and (Compare(A[J], Item) > 0) do begin A[J + 1]:= A[J]; Dec(J); end; A[J + 1]:= Item; end; end; function CompareInt(const L, R: Integer): Integer; begin if L < R then Result:= -1 else if L > R then Result:= 1 else Result:= 0; end; class procedure TArray.InsertionSort(var A: array of T); var P: PTypeInfo; begin P:= TypeInfo(T); case P^.Kind of tkInteger: InternalSort(A, @CompareInt); tkUString: InternalSort(A, @CompareStr); end; end; end.
Note that the function ‘CompareInt’ is declared in interface section. If you comment out interface declaration you get compile error
[DCC Error] GenericSort.pas(54): E2506 Method of parameterized type declared in interface section must not use local symbol ‘CompareInt’.