Today I discovered a compiler bug (QC#108577).
The following program fails to compile:
program Project1;
{$APPTYPE CONSOLE}
procedure P(M: TArray<TArray<Integer>>);
begin
SetLength(M, 1, 2);
end;
begin
end.
The compiler gags on the SetLength
line and says:
[dcc32 Error] E2029 ')' expected but ',' found
I know I could fix it like this:
procedure P(M: TArray<TArray<Integer>>);
var
i: Integer;
begin
SetLength(M, 1);
for i := low(M) to high(M) do
SetLength(M[i], 2);
end;
but naturally I'm keen to avoid having to resort to this.
The following variant compiles and seems to work:
procedure P(M: TArray<TArray<Integer>>);
type
TArrayOfArrayOfInteger = array of array of Integer;
begin
SetLength(TArrayOfArrayOfInteger(M), 1, 2);
end;
I don't know enough about the implementation details of dynamic arrays, TArray<T>
casting, reference counting etc. to be confident that this is safe.
Is there anybody out there who does know enough to say one way or another whether or not this will produce the correct code at runtime?
The compiler intrinsic procedure
SetLength
constructs an array of dimensions on the fly on the stack and callsDynArraySetLength
for any dynamic array, be it generic or not. If a generic array wouldn't be structurally compatible with a regular dynamic array, the same implementation for setting the length possibly wouldn't be called.In fact documentation of
DynArraySetLength
offersSetLength
as an alternative for multi-dimensional arrays.DynArraySetLength
could also be used instead of a typecast, but I don't see any reason to prefer one or the other.By design of the generics implementation, using a manual map to
array of array of Integer
will work.But there is no benefit of using generics here!
Just code:
Note also that such
TArray<>
orarray of ..
are passed by value, and copied on the stack, unless you specifyconst
orvar
:I was recently bitten by the fact that
DynamicArray<T>
andTArray<T>
in C++ are actually implemented differently (DynamicArray
is a standalone class, whereasTArray
is aTObject
descendant), which implies thatarray of T
andTArray<T>
do have some implementation differences in Delphi as well. They certainly produce different types of RTTI, at least. Which was the root cause of a problem in some of my C++ code that started failing when the Delphi compiler started outputtingTArray
typedefs in HPP files for Delphiarray of ...
types instead ofDynamicArray
typedefs.