I'm trying to build an allocatable array with polymorphic elements. A minimal example is the following :
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
Now, the code above works fine and prints out (as expected) :
1 is basetype
2 is exttype2
3 is exttype1
4 is exttype2
5 is exttype1
The problem is, however, once I try to access the component of each extended type (e.g. r1
of exttype1
) by uncommenting the commented part of each write(*,*)
line, my compiler (gfortran 7.5.0) gives the following error :
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
I don't understand why these errors are produced since the compiler obviously recognizes the extended types exttype1
and exttype2
.
What's the correct way to access r1
and r2
?
EDIT :
By changing ary(i)%comp
to this
in each write(*,*)
line, the code compiles normally. What difference does this modification make? How are these two NOT equivalent?