0

How can I determine whether an array item is a reference to another array or another typed item like Single for instance.

I'm looking into this because I would like to make a uniform code that will iterate through all items of a dynamic multidimensional arrays regardless of the number of dimensions that array have.

And I need this in order to determine if I need to recursively iterate through array that represents inner dimension or whether I'm already at innermost dimension.

I assume I might need to rely in RTTI but I must admit I have no experience with RTTI so far.

SilverWarior
  • 7,372
  • 2
  • 16
  • 22
  • 4
    There's no way to discover that information from the variable itself. http://stackoverflow.com/a/554185/33732 See the RTL's implementation of `SetLength` for an example of passing type information to a function that handles arrays of arbitrary dimension. – Rob Kennedy Sep 18 '16 at 23:31
  • @RobKennedy Not in Delphi 6 as I was initially looking for but it is possible in later versions of Delphi as you can see in my answer bellow. – SilverWarior Sep 19 '16 at 18:06

1 Answers1

0

I have found solution for this but it is only available in later versions of Delphi (tested on Delphi 10 Seattle and Delphi 10.1 Berlin) and it relies on undocumented function GetTypeKind that I stumbled upon.

if GetTypeKind(SomeVariable) = tkArray then //Returns true if variable references to static array

if GetTypeKind(SomeVariable) = tkDynArray then //Returns true if variable references to dynamic array

It can be even used for checking the items type of inner arrays

var Dyn2DArray: Array of Array of Integer;

if GetTypeKind(Dyn2DArray[0]) = tkDynArray then //Returns true since item of outmost array is references to inner array

if GetTypeKind(Dyn2DArray[0,0]) = tkDynArray then //Returns false since inner array item is of integer type
SilverWarior
  • 7,372
  • 2
  • 16
  • 22
  • Does it do anything beyond simply `TypeInfo(x)^.Kind`? And does it really work from your function that doesn't already know the type? I assume your real code gets its input as an untyped var parameter. Your demonstrations above are a case where you don't even need it because you can just look at the declaration to get what you need. – Rob Kennedy Sep 19 '16 at 18:19
  • @RobKennedy My real code will use this GetTypeKind to determine if an array item is a reference to another array. If it is then I will recursively call my function passing that array to it. This is just one step in making a function that will iterate through all items of a multidimensional array regardless of how many dimensions does that array have. So now I just need to figure out how do I pass and outermost array of multidimensional array as an argument to a procedure. ... – SilverWarior Sep 19 '16 at 19:23
  • ... And for that I opened a question on embarcadero forums as I believe I might have more luck there as I haven't found any type that would generally define an array. So I suspect that only guys at Embarcadero knows whether something like that is even possible. – SilverWarior Sep 19 '16 at 19:26
  • I see. I suspect what you'll find is that the solution to *this* question ends up being useless because `GetTypeKind` requires the type information be available for the argument at compile time, but your other question will yield an answer that involves not having type information at compile time. All the built-in functions that accept generic array parameters use *compiler magic*, so the compiler automatically provides a hidden type-info argument. Like I said, you can look at `SetLength` to see how it works. You can mimic it, but it won't be automatic, and it won't be hidden. – Rob Kennedy Sep 19 '16 at 19:38
  • @RobKennedy Look at `SetLength` how? If I CTRL+Click on `SetLength` I'm thrown on top of Systems unit. If I put breakpoint at `SetLength` and then press F7 code jumps to some assembly code that I don't understand. Perhaps this is because I only own Professional edition of Delphi and therefore lack some source files. It is the same with Seattle and Berlin. – SilverWarior Sep 19 '16 at 19:55
  • In my copy of *System.pas* from Delphi 2005, I have functions like `DynArraySetLength`, `DynArrayCopyRange`, and `_InitializeArray` that all take a parameter named `typeInfo`, which is declared as type `Pointer`, but which is really a `PTypeInfo`. `DynArraySetLength` is particularly relevant because it's recursive, so it handles nested dynamic-array types specially. – Rob Kennedy Sep 19 '16 at 20:34
  • @Silver - when advancing in the CPU window keep looking at the call stack, when you see DynArraySetLength with a blue dot double click on it. – Sertac Akyuz Sep 19 '16 at 21:10
  • The pointer seems to be of kind PDynArrayTypeInfo which have some additional fields. – Sertac Akyuz Sep 19 '16 at 21:13