Quantcast
Channel: Intel® Software - Intel® Fortran Compiler for Linux* and macOS*
Viewing all articles
Browse latest Browse all 2746

Trouble with polymorphic entities

$
0
0

Hello,

I am experiencing several error messages about polymorphic entities with ifort 14.0.1 (Linux) which I find strange.However, I am relatively new to OO Fortran features, so I am not sure if this is a compiler or a personal problem ;-)

Could anyone of you be so kind and have a look at the following sample code?

     MODULE shapes

      ! A general shape
      TYPE, ABSTRACT :: shape
      CHARACTER :: color *8 = 'black'
      CONTAINS
      PROCEDURE :: list   => shape_list
      END TYPE shape

      ! A specialized shape : a sphere
      TYPE, EXTENDS(shape) :: sphere
      REAL :: radius = 1.0
      CONTAINS
      PROCEDURE :: list   => sphere_list
      END TYPE sphere

      CONTAINS

      SUBROUTINE shape_list(this)
      CLASS(shape), INTENT(IN) :: this
      print '(A6, " = ",A8)', "COLOR", this % color
      END SUBROUTINE

      SUBROUTINE sphere_list(this)
      CLASS(sphere), INTENT(IN) :: this
      CALL this % shape % list                !  <---------------------   error
      print '(A6, " = ",F6.3)', "RADIUS", this % radius
      END SUBROUTINE

      END MODULE

ifort gives me the following error on this:

sample01.f(28): error #8307: If the rightmost part-name is of abstract type, data-ref shall be polymorphic   [SHAPE]
      CALL this % shape % list      !  <---------------------   error
------------------^
sample01.f(28): error #8318: If the component immediately preceding the type-bound procedure is abstract, the entire data reference before the procedure name must be polymorphic.   [SHAPE]
      CALL this % shape % list      !  <---------------------   error

Why is "this" not a polymorphic entity?

Why am I not allowed to call the list method of the (abstract) base class? Since "this" is a real object, everything should be well-defined.

My workaround is to rename the list method of shape to list_base, or to call shape_list directly.

What I actually want to do is to call the list method of the parent class (something like super::list() in C++).
Is there any way to do this in Fortran without mentioning shape explicitely, so I could add a class "round_shape"
between shape and sphere at some later time without having to rename the in list() ?

 ---------------------

Second, I am confused when I am allowed to pass derived types as dummy arguments and when not.

If I add a field currentShape and a subroutine SAVE_ANY_SHAPE to my shape module (*not* to a specific type):

 
      CLASS(shape), POINTER :: currentShape

      ... CONTAINS ...

      SUBROUTINE SAVE_ANY_SHAPE(a_shape)
      CLASS(shape), POINTER, INTENT(IN) :: a_shape
      currentShape => this
      END SUBROUTINE

and have the following main program:

      PROGRAM test
      
      USE shapes
      CLASS(shape),  POINTER :: pshape
      CLASS(sphere), POINTER :: psphere

      ALLOCATE(psphere)
      CALL SAVE_ANY_SHAPE(psphere)  <------------------   error

      END PROGRAM test

I get a compile-time "error #6633: The type of the actual argument differs", but

      ALLOCATE(psphere)
      pshape => psphere
      CALL SAVE_ANY_SHAPE(pshape)

works. Also, if I remove the POINTER attribute and add a TARGET attribute to a_shape, I can call SAVE_ANY_SHAPE with either of pshape and psphere as argument without error. Is this really how it should be? Why are targets polymorphic and pointers not?

Thank you for your hints!

   Christopher


Viewing all articles
Browse latest Browse all 2746

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>