- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
with respect to your first question: "this" is a polymorphic entity, but "this%shape", being a reference to the abstract parent type, is not. Disallowing an object to be of abstract dynamic type is a fundamental property of the concept, by the way. From the point of view of re-using your template method in overrides, you could replace
CALL this % shape % list
by
CALL shape_list(this)
As far as your second question is concerned: If a polymorphic dummy argument has the POINTER or ALLOCATABLE attribute, the actual argument is required to have the same declared type as the dummy. The reason for this is that the type compatibility rules must be applied in two ways: First, the incoming object must be either of the same type or an extension of that of the dummy. Second, an allocation or pointer assignment inside the procedure may cause the dynamic type of the object to become, at worst, the declared type of the dummy. Hence, on return from the procedure you'd get an inconsistency if the actual argument were of an extension type of the declared type of the dummy.
(Note that the pointer assignment inside your SAVE_ANY_SHAPE is to an undeclared entity "this"; presumably it should be to "a_shape"?
Regards
Reinhold
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I will also note that it's a bit odd to declare a non-deferred type bound procedure and data components in an abstract type in this context. Typically, the point of an abstract type is to define the methods which the concrete type should implement, and their interfaces. It is an interface specification/contract tool. Sure, it can have default data elements, and perhaps some non-override-able default methods, but it must have a concrete implementation to be used. (You can only use these methods and data components from a concrete type which extends it.)
You could simply remove 'abstract' from the type declaration and I think it would work. Also, if you don't overload list, i.e. keep distinct names you could CALL this%shape_list which sphere inherits from shape.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page