Доступ к компонентам расширенного типа в конструкции SELECT TYPE - PullRequest
2 голосов
/ 25 марта 2020

Я пытаюсь создать размещаемый массив с элементами c полиморфи. Ниже приведен минимальный пример:

program PolyArray

implicit none

type basetype
    integer :: ib
end type basetype

type, extends(basetype) :: exttype1
    real    :: r1
end type exttype1

type, extends(exttype1) :: exttype2
    real    :: r2
end type exttype2

type arraytype
    class(basetype), allocatable :: comp
end type arraytype

type(arraytype), dimension(:), allocatable :: ary
integer :: N, i 

N = 5
allocate (ary(N))
do i=1,N; if (mod(i,2)==0) then
    allocate(exttype2::ary(i)%comp)
     else if (       i==1) then
    allocate(basetype::ary(i)%comp)
        else
    allocate(exttype1::ary(i)%comp)
end if; end do

do i=1,N; select type (this=>ary(i)%comp)
    type is (basetype)
        write(*,*) i, "is basetype"!, "%ib =", ary(i)%comp%ib
    type is (exttype1)
        write(*,*) i, "is exttype1"!, "%r1 =", ary(i)%comp%r1
    type is (exttype2)
        write(*,*) i, "is exttype2"!, "%r2 =", ary(i)%comp%r2
    class default
        write(*,*) i, "is unknown type !"
end select; end do

end program PolyArray

Теперь приведенный выше код работает нормально и выводит на печать (как и ожидалось):

           1 is basetype
           2 is exttype2
           3 is exttype1
           4 is exttype2
           5 is exttype1

Однако проблема заключается в том, что когда я пытаюсь Получив доступ к компоненту каждого расширенного типа (например, r1 из exttype1), раскомментировав закомментированную часть каждой строки write(*,*), мой компилятор (gfortran 7.5.0) выдает следующую ошибку:

         write(*,*) i, "is exttype1", "%r1 =", ary(i)%comp%r1
                                                            1
Error: 'r1' at (1) is not a member of the 'basetype' structure
poly.f90:40:60:

         write(*,*) i, "is exttype2", "%r2 =", ary(i)%comp%r2
                                                            1
Error: 'r2' at (1) is not a member of the 'basetype' structure

Я не понимаю, почему возникают эти ошибки, поскольку компилятор явно распознает расширенные типы exttype1 и exttype2. Как правильно получить доступ к r1 и r2?

РЕДАКТИРОВАТЬ: При изменении ary(i)%comp на this в каждой строке write(*,*) код компилируется нормально. Какая разница эта модификация? Как эти два НЕ эквивалентны?

1 Ответ

1 голос
/ 25 марта 2020

В конструкции выбора типа, где каждый имеет

select type (this=>ary(i)%comp)

, есть две вещи: селектор и ассоциированное имя . ary(i)%comp здесь - селектор, а this - имя ассоциированного участника.

Мы знаем, что в этом случае требуется имя ассоциированного пользователя *1013*, поскольку ary(i)%comp не является именем.

Однако ассоциированное имя не просто для удобства (как оно может быть в ассоциированной конструкции): оно имеет фундаментальное обязательное свойство, которое вам нужно здесь. В блоках, управляемых защитниками типов, переменная, заданная ассоциированным именем, имеет объявленный тип охранника типов; селектор сохраняет объявленный тип, как это было за пределами конструкции.

Наличие желаемого объявленного типа позволяет нам получить доступ к компонентам; просто наличие типа c не имеет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...