Hi Stefano,
>I ran into some troubles understanding how type bound operator overloading
>works.
...
>The issue is that I don not know if the attached code is valid Fortran.
It is not.
>Some compilers as intel and nag
The NAG compiler rejects your program with
Error: sk9b.f90, line 34: Ambiguous specific type-bound procedures EQ_EXTENSION
and EQ_BASE for type-bound generic OPERATOR(.EQ.) in type BASE
Both the ancient 5.2 release and the more recent 5.3.1 release reject this with
the same message...
>Could you help me out to understand how operator overloading works properly?
Since you are trying to do something that would be inherently ambiguous -
CLASS(base) accepts everything that CLASS(extension) accepts - you need to use
overriding (and thus dynamic dispatch) to get the result you want. Overriding
only solves this for one argument though, handling the second argument is best
done with type enquiry.
> MODULE my_mod
>
> TYPE :: base
> INTEGER :: a
> CONTAINS
> PROCEDURE, PRIVATE :: eq_base
> GENERIC, PUBLIC :: OPERATOR(==) => eq_base
> END TYPE
>
> TYPE, EXTENDS(base) :: extension
> INTEGER :: b
> CONTAINS
REPLACE> PROCEDURE, PRIVATE :: eq_extension
PROCEDURE,PRIVATE :: eq_base => eq_extension
DELETE > GENERIC, PUBLIC :: OPERATOR(==) => eq_extension
> END TYPE
COMMENT: This makes eq_base (and thus ==) dispatch to eq_base when the first
argument is TYPE(base), and eq_extension when the first argument is
TYPE(extension). Handling the second argument is best done within those
routines.
> CONTAINS
>
> ELEMENTAL LOGICAL FUNCTION eq_base(c1, c2)
> CLASS(base), INTENT(IN) :: c1, c2
REPLACE> eq_base = .FALSE.
REPLACE> IF (c1%a/=c2%a) RETURN
REPLACE> eq_base = .TRUE.
eq_base = SAME_TYPE_AS(c1,c2) .AND. c1%a==c2%a
> END FUNCTION
>
> ELEMENTAL LOGICAL FUNCTION eq_extension(c1, c2)
REPLACE> CLASS(extension), INTENT(IN) :: c1, c2
CLASS(extension),INTENT(IN) :: c1
CLASS(base),INTENT(IN) :: c2
COMMENT: c2 needs to be declared CLASS(base) because
(1) it was declared CLASS(base) in eq_base ... only the "passed object" dummy
varies the type;
(2) so it can handle "extension==base".
REPLACE> eq_extension = .FALSE.
REPLACE> IF (.NOT.(c1%base==c2%base)) RETURN
REPLACE> IF (c1%b/=c2%b) RETURN
REPLACE> eq_extension = .TRUE.
IF (.NOT.SAME_TYPE_AS(c1,c2)) THEN
eq_extension = .FALSE.
ELSE
SELECT TYPE(c2)
CLASS IS (extension) ! Guaranteed to execute since same type.
eq_extension = c1%a==c2%a .AND. c2%b==c2%b
END SELECT
END IF
COMMENT: The SELECT TYPE is to get access to the components of c2 added by the
type "extension", i.e. to c2%b.
> END FUNCTION
>
> END MODULE
>
> PROGRAM main
>
> USE my_mod
>
> TYPE(base) :: b = base(1)
> TYPE(extension) :: e = extension(1,2)
>
> PRINT *, b == b ! => T
> PRINT *, base(2) == e ! => F
> PRINT *, e == base(2) ! => F
> PRINT *, e == e ! => T
>
> END PROGRAM
With these changes, your program prints "T F F T" (on 4 lines) with the current
NAG compiler release (5.2 did not have the SAME_TYPE_AS intrinsic).
Cheers,
--
................................Malcolm Cohen, Nihon NAG, Tokyo.
|