fortranderived-types

defining default values for an array of derived data type


In fortran you can define a default value for a variable on declaration which can be overwritten later in the code, also giving default values for all entries in an derived type array as follows:

PROGRAM test
TYPE data
  INTEGER :: j=0
  CHARACTER(len=10)::label="hello"
END TYPE data
TYPE(data) :: obj(2)

! overwrite the default of 0 in the first array entry
obj(1)%j=6  ! etc etc

END PROGRAM test

all very straightforward. But what is the syntax used for defining a default set of values for all array entries of derived datatypes? I looked up a few tutorials, but none of them addressed this. In other words, to have j=0 in the first element of obj%j by default and set it to 1 in the second and so on...

PROGRAM test

TYPE data
  INTEGER :: j
  CHARACTER(len=10)::label
END TYPE data

TYPE(data) :: obj(2)=??? ! what do I put to define an array of default types?

! for example these might be my desired default values
obj(1)%j=0
obj(1)%label="bad"
obj(2)%j=1
obj(2)%label="good"

END PROGRAM test

Solution

  • First a note on terminology: in a statement like

    integer, save :: i=1
    

    this doesn't provide a "default" value for i, it provides an initial value for i. We call this explicit initialization. (Note how I've put the SAVE attribute there just to make it obvious; the attribute is implicit.)

    The syntax for such explicit initialization is the same whether the object is of intrinsic or derived type, a scalar or an array:

    type(decl_type), save[, attributes] :: myobj = initial_expression
    

    where decl_type is integer, real, my_type, etc. (type(integer) can of course be written as the simple integer.)

    For derived type, we just need to find a suitable initialization expression.

    For an array myobj this expression can be a scalar (in which case all elements of the array initially have that value), or an array. Obvious cases use the default structure constructor:

    type(my_type), save               :: myobj1 = decl_type(comps)
    type(my_type), save, dimension(2) :: myobj2 = decl_type(comps)
    type(my_type), save, dimension(2) :: myobj3 = [decl_type(comps1), decl_type(comps2)]
    

    If you want to construct an array using the structure constructor, note that you need an array constructor: the structure constructor isn't elemental.

    More generally we can use things other than the default structure constructor, but the expression must be a constant expression.

    To provide an example suiting the question:

    implicit none
    
    type data
      integer :: j
      character(10) :: label
    end type data
    
    type(data), save, dimension(2) :: mydata=[data(0,"bad"), data(1,"good")]
    
    end
    

    Finally, if the derived type has default initialization for components, they can be omitted from the structure constructor:

    implicit none
    
    type data
      integer :: j=-1
      character(10) :: label="nothing"
    end type data
    
    type(data), save, dimension(2) :: mydata=data()
    
    end