arraysfortranfortran2008

Fortran 2008 - array variable in class


I have a following class, where I need to store objects of type neuron_t and connection_t.

!> Class representing a general network
type :: net_t
    private

    character(:), allocatable                 :: net_type              !< Type of the net
    integer(kind=integer_4neuro)              :: num_of_neurons        !< Number of neurons in the net
    character(:), allocatable                 :: training_method       !< Used training method

    class(neuron_t), allocatable              :: neuron_arr(:)         !< Array containing all neurons
    integer(kind=integer_4neuro), allocatable :: input_neuron_arr(:)   !< Array of input neuron indices
    integer(kind=integer_4neuro), allocatable :: output_neuron_arr(:)  !< Array of output neuron indices
    class(connection_t), allocatable          :: connection_arr(:)     !< Array of all connections

contains
    !> Prints information about the network to the standard output.
    procedure :: print_info => print_info_impl

    !> Saves the network instance to the Fortran binary file
    procedure :: save_net_bin => save_net_bin_impl

end type net_t

interface net_t
    !> Constructor of net_t class
    !! Loads complete info about network from file
    !! @param[in] filepath Path to the file with network configuration
    !! @return Returns pointer to the new instance of the class net_t
    module procedure :: new_net_1
end interface net_t

I tried to initialize the array like this

    allocate(new_obj)

    ! Init object
    do i=1,5
        new_obj%neuron_arr(i) =  mock_neuron_t()
    end do

but I'm getting the following error:

         new_obj%neuron_arr(i) =  mock_neuron_t()
        1
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator

Do you know, what am I doing wrong? mock_neuron_t extends type neuron_t, so it should be ok.

EDIT:

Both neuron_t and connection_t classes are abstract, so I'm getting following error now after adding allocate(new_obj%neuron_arr):

     allocate(new_obj%neuron_arr)
             1
Error: Allocating new_obj of ABSTRACT base type at (1) requires a type-spec or source-expr

         new_obj%neuron_arr(i) =  mock_neuron_t()
        1
Error: Nonallocatable variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator

Solution

  • You cannot just assign to a polymorphic variable in an intrinsic assignment (=). You can only do that for allocatable variables and an array element is not an allocatable variable eventhough it is a part of an allocatable array. Remember all array elements must have the same dynamic type.

    So if you wanted to have different elements of neuron_arr(:) to have a different type, that is not allowed.

    But you can allocate the array to some single type and use the select type typeguard.

    allocate(new_obj)
    
    allocate(new_obj%neuron_arr)  !this allocates it to the declared type neuron_t!
    
    ! Init object
    select type(a => new_obj%aneuron_arr)
      type is(neuron_t)
        do i=1,5
          a(i) =  mock_neuron_t()
        end do
    end select
    

    But then, if you will always have one fixed type there, wouldn't type(neuron_t) just suffice?