Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

Unlimited polymorphic variables

Fahim_F_
Novice
2,548 Views

Good evening,

I have a problem using polymorphic variables and I appreciate any help I can get from you. The problem is that when I allocate a type to a polymorphic varibale, this variable does not recognize the properties of that type. Please have a look at the simple example I made.

Consider an object shape with two childs named rec and circ. Another object which is named usedshape has a polymorphic variable of class (shape). Now for different occasions,  I want to assign, rect or circ to useshape%shape and I expect that useshape%shape has the properties (and functionalities) of circ or rect whichever is assigned. However, it does not work for me. I also tried defining the polymorphic variable by class (*) which should be able to assign any type to it, but it does not work

Any comments on this problem is appreciate. If this is impossible, how can I get around this problem?

Thank you very much for your time

* I am using Intel fortran 2013 (Compiling with Intel(R) Visual Fortran Compiler XE 12.0.0.104 [IA-32])

0 Kudos
12 Replies
Steven_L_Intel1
Employee
2,548 Views

You can't do much of anything with an unlimited polymorphic unless you are inside a SELECT TYPE construct. Even if you have just allocated it to a type, you can't treat it as an object of that type unless you're inside a SELECT TYPE case for that type.

0 Kudos
Fahim_F_
Novice
2,548 Views

Thanx Steve for the propmt answer. Do u have any comment on how can I get this flexibility that i need in the code? I have an object similar to useshape which it contains another object shape which should be polymorohic, meaning get the objects of differnet kind like circ or rect. Any comment on how to design and code such a situation would be very appreciated.

Thank you very much in advance

0 Kudos
Simon_Geard
New Contributor I
2,548 Views

I've tried including the select type in the example but still can't get it to compile

[fortran]

select case (var)
case (1)
    allocate ( rect :: useshape_test%SH )
    select type(useshape_test%SH)
    type is (rect)
        useshape_test%SH%rsize = 4
        allocate (useshape_test%SH%rprop(1:4))
    end select
case (2)
    allocate (circ :: useshape_test%SH)
    select type(useshape_test%SH)
    type is (circ)
        useshape_test%SH%rsize = 4
        allocate (useshape_test%SH%rprop(1:4))
    end select
    useshape_test%SH%csize = 10
    allocate (useshape_test%SH%cprop(1:10))
end select
[/fortran]

C:\Program Files (x86)\Intel\Composer XE 2013.149>ifort /c source1.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 13.1.0.149 Build 20130118
Copyright (C) 1985-2013 Intel Corporation.  All rights reserved.

source1.f90(80): error #8253: If selector expression in SELECT TYPE is not a named variable, associate-name=> shall appear.
    select type(useshape_test%SH)
----^
source1.f90(82): error #6460: This is not a field name that is defined in the encompassing structure.   [RSIZE]
        useshape_test%SH%rsize = 4
-------------------------^
source1.f90(83): error #6460: This is not a field name that is defined in the encompassing structure.   [RPROP]
        allocate (useshape_test%SH%rprop(1:4))
-----------------------------------^
source1.f90(87): error #8253: If selector expression in SELECT TYPE is not a named variable, associate-name=> shall appear.
    select type(useshape_test%SH)
----^
source1.f90(92): error #6460: This is not a field name that is defined in the encompassing structure.   [CSIZE]
    useshape_test%SH%csize = 10
---------------------^
source1.f90(93): error #6460: This is not a field name that is defined in the encompassing structure.   [CPROP]
    allocate (useshape_test%SH%cprop(1:10))
-------------------------------^
compilation aborted for source1.f90 (code 1)

C:\Program Files (x86)\Intel\Composer XE 2013.149>

What have I done wrong?

0 Kudos
Steven_L_Intel1
Employee
2,548 Views

The error messages are rather clear to me - did you not understand them?

The following compiles

[fortran]
module testing

    implicit none
    private
    public :: shape , circ , rect , useshape
   
    type shape
        character(4) :: s_name
    end type shape
   
    type , extends (shape) :: rect
        integer :: rsize
        real , dimension(:) , allocatable :: rprop
        contains
        procedure sumprop => rect_sumprop
    end type
        
    type , extends (shape) :: circ
        integer :: csize
        real , dimension(:) , allocatable :: cprop
        contains
        procedure sumprop => circ_sumprop
    end type
    
    type useshape
        character(4) :: us_name
        class (*) , allocatable :: SH
 !       class (shape) , allocatable :: SH
        contains
        procedure :: Comp
    end type
    
    contains
    
    function rect_sumprop(this)
        implicit none
        real :: rect_sumprop
        class (rect) :: this
        integer :: i
        rect_sumprop = 0.
        do i=1 , this%rsize
            rect_sumprop = rect_sumprop + this%rprop(i)
        end do
    end function
   
    function circ_sumprop(this)
        implicit none
        real :: circ_sumprop
        class (circ) :: this
        integer :: i
        circ_sumprop = 0.
        do i=1 , this%csize
            circ_sumprop = circ_sumprop + this%cprop(i)
        end do
    end function    
    
    function comp(this)
        implicit none
        real :: comp
        class (useshape) :: this
        comp = 0.
!        comp = this%SH%sumprop()
    end function
        
end module testing
    
program main
use testing
implicit none


integer :: var
type (useshape) :: useshape_test

var = 2

select case (var)
case (1)
    allocate ( rect :: useshape_test%SH )
    select type(selector=>useshape_test%SH)
    type is (rect)
        selector%rsize = 4
        allocate (selector%rprop(1:4))
    end select
case (2)
    allocate (circ :: useshape_test%SH)
    select type(selector=>useshape_test%SH)
    type is (circ)
        selector%csize = 4
        allocate (selector%cprop(1:4))
    end select
end select
end program
[/fortran]

0 Kudos
Fahim_F_
Novice
2,548 Views

Thanx for your comment Steve. I got the idea of polymorphic variables I guess. However, the code you provided does not run for var=2 correctly (although  it does compile but when debugging with var=2, the selector%csize is not defined) !!! However, it does work for var=1. Is this a problem with the compiler??

0 Kudos
Steven_L_Intel1
Employee
2,548 Views

How does it "not run"? It seems to run fine for me.

0 Kudos
Fahim_F_
Novice
2,548 Views

Oh, you are right, My problem was using selector outside the select type construct. It does run.

however, is there a way that I point a polymorphic pointer (like useshape%SH) to any of circ or rect objects and then use it without a select type construct. For example, in the main program I need to do :

program main
use testing
implicit none
integer :: var
type (useshape) :: useshape_test
var = 1
select case (var)
case (1)
allocate ( rect :: useshape_test%SH )
select type(selector=>useshape_test%SH)
type is (rect)
selector%rsize = 4
allocate (selector%rprop(1:4))
selector%rprop(1:4) = 3
end select
case (2)
allocate (circ :: useshape_test%SH)
select type(selector=>useshape_test%SH)
type is (circ)
selector%csize = 5
allocate (selector%cprop(1:5))
selector%cprop(1:5) = 10
end select
end select

select type (selector=>useshape_test%SH)
type is (circ)
print*, selector%sumprop()
type is (rect)
print*, selector%sumprop()
end select

read*
end program

Instead I would like to able to do sth like:

print*, useshape_test%SH%sumprop()

With the select type construct, verytime that I use a procedure of the object assigned to useshape_test%SH, I need to use a select type construct, which results in repreating a piece of code several times !! Is the a way around this?

thank you very much

0 Kudos
Steven_L_Intel1
Employee
2,548 Views

No. The language requires the SELECT TYPE in order for you to name any of the dynamic type's components.  Maybe you can use type extension rather than unlimited polymorphic?

0 Kudos
IanH
Honored Contributor III
2,548 Views

The OP should also have a look at the SOURCE specifier in an allocate statement.  This is shown below, using a structure constructor to specify the initial value of the components in the allocated object.  Instead of the structure constructor you could have a function that constructs your Rect (or circle) object just the way you want...

[fortran]ALLOCATE( useshape_test%SH, SOURCE=Rect( RSIZE=4, RPROP=[0.0, 0.0, 0.0, 0.0]))[/fortran]

For the most recent query - put aspects that are common between the types into the parent type - for instance both types have a sumpop binding - is that going to be common to all shapes?.  If so, make that a binding of the parent shape type and override that binding in the extensions.  You can then call that binding on any object that has a declared type of Shape, without needing to use SELECT TYPE.

0 Kudos
Fahim_F_
Novice
2,548 Views

Thank you IanH and Steve for your comments. 

0 Kudos
Simon_Geard
New Contributor I
2,548 Views

[fortran]

 select type(selector=>useshape_test%SH)

[/fortran]

I didn't realize that useshape_test%SH was not a named variable in this context and that therefore the associate-name was required so thanks for that.

I still haven't got to grips with this new moderation of this forum. I posted yesterday morning (uk time) and watched for my post during the afternoon but nothing appeared. This morning I arrive and there seems to have been a whole conversation which has moved the thread's topic on. I guess you had a reason for changing from the captcha scheme but at least with that my posts went up at the right time. If we have to wait for human moderators in one timezone then the inherent latency will severely limit the usefulness of this forum. 09:33.

0 Kudos
Steven_L_Intel1
Employee
2,548 Views

I hope that the moderation issue will be resolved soon.

0 Kudos
Reply