简体   繁体   中英

Access extended type components in a SELECT TYPE construct

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 (eg 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?

In the select type construct where one has

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

there are two things: the selector and the associate name . ary(i)%comp is the selector here and this is the associate name.

We know that an associate name is required in this case, because ary(i)%comp is not a name.

However, the associate name isn't just for convenience (like it may be in an associate construct): it has the fundamental required property that you need here. In the blocks governed by the type guards, the variable given by the associate name has declared type of the type guard; the selector retains the declared type as it had outside the construct.

Having the desired declared type allows us to access the components; simply having the dynamic type doesn't.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM