This is difficult to do cleanly in Fortran 90. It is straight forward in Fortran 2003.
Resolution of the procedure to call when the generic reference fun
is encountered (in CALL fun(pt)
) is done at compile time, based on the declared type of pt
.
If you are limited to Fortran 90, then effectively you will need to maintain a flag of some sort that indicates at runtime which particular derived type you want to work with, have a named object for each of type A and type B, and everytime you want to reference fun
have an IF construct that selects the correctly named argument.
(If the size of the objects is significant you can arrange for them to have common storage.)
Something like:
TYPE(A) :: pt_A
TYPE(B) :: pt_B
...
IF (input .EQ. 'A') THEN
CALL fun(pt_A)
ELSE
CALL fun(pt_B)
END IF
In F2003, you would define a common parent type, that had a specific binding named fun. pt
would then be a polymorphic allocatable object, allocated based on input to either type A or type B as appropriate.
TYPE :: Parent
CONTAINS
PROCEDURE(parent_Fun), DEFERRED :: Fun
END TYPE Parent
ABSTRACT INTERFACE
SUBROUTINE parent_Fun(obj)
IMPORT :: Parent
IMPLICIT NONE
CLASS(Parent), INTENT(IN) :: obj
END SUBROUTINE parent_Fun
END INTERFACE
TYPE, EXTENDS(Parent) :: A
REAL :: x, y
CONTAINS
PROCEDURE :: A => A_Fun
END TYPE A
TYPE, EXTENDS(Parent) :: B
INTEGER :: x, y
CONTAINS
PROCEDURE :: B => B_Fun
END TYPE B
CLASS(Parent), ALLOCATABLE :: pt
...
IF (input .EQ. 'A') THEN
ALLOCATE(A:: pt)
ELSE
ALLOCATE(B:: pt)
END IF
...
CALL pt%Fun()