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