Fortran 2008 - переменная массива в классе

У меня есть следующий класс, где мне нужно хранить объекты типа neuron_t и 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

Я попытался инициализировать массив следующим образом

    allocate(new_obj)

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

но я получаю следующую ошибку:

         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

Знаете, что я делаю не так? mock_neuron_t расширяет тип neuron_t, так что все должно быть в порядке.

РЕДАКТИРОВАТЬ:

Оба класса neuron_t и connection_t являются абстрактными, поэтому после добавления 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

person Eenoku    schedule 03.06.2018    source источник
comment
Аналогичные stackoverflow.com/questions/ 49616410/   -  person Vladimir F    schedule 03.06.2018


Ответы (1)


Вы не можете просто присвоить полиморфную переменную во внутреннем присваивании (=). Вы можете сделать это только для размещаемых переменных, а элемент массива не является размещаемой переменной, даже если он является частью размещаемого массива. Помните, что все элементы массива должны иметь один и тот же динамический тип.

Поэтому, если вы хотите, чтобы разные элементы neuron_arr(:) имели разный тип, это не разрешено.

Но вы можете выделить массив какому-то одному типу и использовать защиту типа select type.

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

Но тогда, если у вас всегда будет один фиксированный тип, не будет ли достаточно type(neuron_t)?

person Vladimir F    schedule 03.06.2018
comment
Большое спасибо! Честно говоря, я думал, что class(neuron_t) твердо установит свой тип на neuron_t... А type(neuron_t) я не могу использовать, потому что neuron_t - это абстрактный класс. - person Eenoku; 03.06.2018
comment
Затем вы должны выделить массив в стетементе выделения для правильного типа и использовать этот тип в select type. Но я боюсь, что ваш дизайн неверен. Массив должен быть выделен сразу под один общий неабстрактный тип). alocate(the_type :: the_array(size)) - person Vladimir F; 04.06.2018
comment
Я пробовал это (см. Редактировать 2 в моем вопросе), но я получаю ошибку сегментации... Я действительно понятия не имею, что сейчас не так... - person Eenoku; 04.06.2018
comment
Кто знает, я думаю, что это должен быть новый вопрос с новым минимально воспроизводимым примером. - person Vladimir F; 04.06.2018
comment
Хорошо, скину сюда ссылку, если интересно. - person Eenoku; 04.06.2018
comment
Я нашел ошибку - конструктор mock_neuron_t возвращал указатель вместо самого экземпляра. Вставьте эту информацию, пожалуйста, в свой ответ, я думаю, она заслуживает принятия. - person Eenoku; 04.06.2018
comment
Я рекомендую никогда не использовать функции, возвращающие указатели. Но я не думаю, что это относится к этому ответу. Это другая проблема для нового вопроса. Я бы предпочел удалить ваше Редактировать 2. Как я могу вообще на него ответить, если вы не показываете соответствующий код? - person Vladimir F; 04.06.2018