I have just found another strange behavior:
program simple;
uses
SysUtils;
type
tStringArray = array of string;
tIntegerArray = array of integer;
tDoubleArray = array of double;
procedure a(const x: tStringArray);
begin
writeln('In strings');
end;
procedure a(const x: tIntegerArray);
begin
writeln('In integers');
end;
procedure a(const x: array of double);
begin
writeln('In doubles');
end;
procedure aa(const x: array of const); // TRY renaming it to a instead of aa
begin
Writeln('In const');
end;
var
v1: tStringArray;
v2: array of integer;
v3: tDoubleArray;
begin
a(['a','b']); // if const exists then that is called, otherwise the correct one
a([12,23]); // same here
a([12.34, 45.67]); // same here
v1 := []; a(v1); // works, always calling the right one
v2 := []; a(v2); // same here
v3 := []; a(v3); // same here
a([]); // only compiles when "const" is there OR there is one and only one with "array of something"
Sleep(500);
end.
I tried various combinations AND added a new version with "array of const" (there there is not even a possibility to make a new type, "type tConstArray = array of const"). I named it to "aa", but you can rename it to "a" to see the difference.
If the new const version is there then all bracket (constant) versions are calling the new routine and only the variable versions (v1, v2, v3) call the correct one (regardless how v was defined as a pre-defined type or an array of something).
If const version is not there, but from the three others (string, integer, double) there is one and only one defined array of something (in this case the double) then the non-empty brackets and the variables call the right one and the empty one calls the only "array of something" version.
If const is not there and there is zero or more than one "array of something" version of a, then the empty bracket does not compile.
I find it a very strange behavior. If for [12, 34] the compiler knows that it is an array of integers when there is no const version, then why does it call the array of const version when it is there. I could expect two different behaviors, either that (a) since it knows that [12, 34] is integer, it would call the integer version and disregard the array of const version OR (b) it would say that it is either the integer version or there is a new const version both suitable to be called, so it cannot decide (like in other examples would give a compile error), but I do not see how it can work both with and without the const version and do different things.
It seems that the array of const version has a priority over all other versions, what is especially strange knowing that array of const passes on a Variable type, what is much less efficient both in terms of memory and processing.
The beauty of the thing is that it gives me a working, but a bit ugly solution. going back to the original problem. If I change the parameters to the tIntegerArray type for most overloaded versions except one then it always work as intended. If the array is not empty, it calls the right overloaded version, while if it is empty it calls the one defined with "array of something" version.
If I want to make my code more coherent and a bit more elegant (though still a bit ugly), I can make all valid, used versions like tIntegerArray, tDoubleArray, etc. and make one more dummy version like "array of byte" or some other type never used and use that for handling the empty arrays.