Search code examples
delphi

Initialize a constant that is a dynamic array of fixed arrays?


Can I initialize a constant dynamic array of arrays?

If:

type
  tNamePair = array[1..2] of String;
  tPairList = array of tNamePair;

How can I create an initialized constant? I can't get the code below compile:

const
  PairList: tPairList = ( ('One', '1'), 
                          ('Two', '2'),
                          ('Three', '3'));

If that's not possible, can a constant fixed array be initialized with a fixed array:

 type
    tPairList: array[1..3] of tNamePair;

If that's not possible, can a constant dynamic array be initialized with a record:

tNamePair = record 
              English: String;
              Number: String;
            end;           
tPairList = array of tNamePair;

if that's not possible can a constant fixed array be initialized with a record:

tNamePair = record 
              English: String;
              Number: String;
            end;           
tPairList = array[1..3] of tNamePair;

If that's not possible, any suggestions other than just hardwiring assignments in the code, which frankly would have taken me less time than composing this question!


Solution

  • Prior to XE7 you could not create dynamic array constants. Constants have to be known at compile time, but dynamic arrays are allocated at runtime.

    A fixed array of fixed arrays can be declared at compile-time:

    type
      tNamePair = array[1..2] of String;
      tPairList = array[1..3] of tNamePair;
    
    const
      PairList: tPairList = ( ('One', '1'),
                              ('Two', '2'),
                              ('Three', '3'));
    

    A fixed array of records can also be declared at compile-time:

    type
      tNamePair = record
                  English: String;
                  Number: String;
                end;
      tPairList = array[1..3] of tNamePair;
    
    const
      PairList: tPairList = ( (English: 'One'; Number: '1'),
                              (English: 'Two'; Number: '2'),
                              (English: 'Three'; Number: '3'));
    

    If you need a dynamic array, you have to construct it at run-time. You can either build it up directly:

    type
      tNamePair = array[1..2] of String;
      tPairList = array of tNamePair;
    
    var
      PairList: tPairList;
    
    initialization
      SetLength(PairList, 3);
      PairList[0][1] := 'One';
      PairList[0][2] := '1';
      PairList[1][1] := 'Two';
      PairList[1][2] := '2';
      PairList[2][1] := 'Three';
      PairList[2][2] := '3';
    end.
    

    Or you can define a compile-time constant fixed array and copy it into the dynamic array at run-time:

    type
      tNamePair = array[1..2] of String;
      tPairList = array[1..3] of tNamePair;
      tPairListDyn = array of tNamePair;
    
    const
      PairList: tPairList = ( ('One', '1'),
                              ('Two', '2'),
                              ('Three', '3'));
    
    function MakePairListDyn(const Pairs: tPairList): tPairListDyn;
    var
      I, J: Integer;
    begin
      SetLength(Result, Length(Pairs));
      J := 0;
      for I := Low(Pairs) to High(Pairs) do begin
        Result[J] := Pairs[I];
        Inc(J);
      end;
    end;
    
    var
      Pairs: tPairListDyn;
    
    initialization
      Pairs := MakePairListDyn(PairList);
    end.
    

    For the situation post XE7 see @LURD's answer.