Гетерогенный массив классов Фортрана - PullRequest
0 голосов
/ 05 июня 2018

У меня есть абстрактный тип и несколько типов, которые наследуются от него.Теперь мне нужно создать массив экземпляров этих унаследованных типов, но я не уверен, возможно ли это даже в Фортране.

Я пытался создать какой-нибудь тип оболочки, как в Созданиегетерогенные массивы в Фортране .

module m
implicit none

type, abstract :: a
    integer, public :: num 
end type a

type, extends(a) :: b
end type b

type, extends(a) :: c
end type c

type :: container
    class(*), allocatable :: ptr 
end type
end module m

program mwe 
use m

type(b) :: b_obj
class(*), allocatable :: a_arr(:)

b_obj = b(1)

allocate(container :: a_arr(3))
a_arr(1) = container(b_obj)

end program mwe 

Но я получаю эту ошибку:

test3.f90:28:25:

 a_arr(1) = container(b_obj)
                     1
Error: Can't convert TYPE(b) to CLASS(*) at (1)

Что я делаю не так?Или есть какой-то другой, правильный способ сделать это?


Попытка 2

Я отредактировал код в соответствии с ответом Франческа:

program mwe 
use m

type(b) :: b_obj
type(c) :: c_obj
type(container), allocatable :: a_arr(:)
integer :: i

b_obj = b(1)
c_obj = c(2)

allocate(container :: a_arr(3))
a_arr(1)%ptr = b(1)
a_arr(2)%ptr = c(3)
a_arr(3)%ptr = c(1000)

do i=1,3
    write(*,*) a_arr(i)%ptr%num
end do

end program mwe 

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

test3.f90:36:35:

     write(*,*) a_arr(i)%ptr%num
                               1
Error: ‘num’ at (1) is not a member of the ‘__class__STAR_a’ structure

1 Ответ

0 голосов
/ 05 июня 2018

Как прокомментировал IanH , описывая выбранный вами подход, текущая версия gfortran

не поддерживает определение неограниченного полиморфного компонента с помощью конструктора структуры

container(b_obj) это такая вещь.Таким образом, оставляя в стороне вопрос о том, по-прежнему ли вы сталкиваетесь с этой проблемой, можно по-прежнему интересоваться разрешением использовать код более старым версиям / другим компиляторам.

Альтернативный подход состоит в том, чтобы не использовать конструктор для элементаваш контейнер.Вместо этого один компонент может быть представлен непосредственно в присваивании:

use m
type(container) a_arr(3)  ! Not polymorphic...
a_arr%ptr = b(1)          ! ... so it has component ptr in its declared type
end mwe

Естественно, у нас все еще есть компонент типа контейнера, полиморфный, поэтому любые попытки ссылаться / определять / и т. Д., Этот компонент будетс учетом этих различных ограничений.В вашем вопросе у вас есть компонент unlimited polymorphic, но я вижу, что вы сначала говорите об ограничении рассмотрения контейнера элементами, которые расширяют первый тип.Вместо того, чтобы объявлять контейнерный компонент как неограниченный полиморфный, он может быть гораздо полезнее объявленного типа a:

type :: container
    class(a), allocatable :: ptr 
end type

Это будет достаточно для решения проблемы с

do i=1,3
    write(*,*) a_arr(i)%ptr%num
end do

, потому чтоnum является компонентом объявленного типа a_arr(i)%ptr (то есть. a).В общем, это не полное решение, потому что

do i=1,3
    write(*,*) a_arr(i)%ptr%num_of_type_b
end do

не будет работать (с num_of_type_b компонентом в расширяющем типе).Здесь вы должны использовать обычные приемы (определенный ввод / вывод, динамическое разрешение, select type и т. Д.).Они выходят за рамки этого ответа, и многие другие вопросы можно найти по ним.

...