Reputation: 3852
As the following code sample shows, person_list
is a user-derived type and contains a type-bound procedure compare_persons
. I would like compare_persons
to be able to accept a certain group of compareFunc
as one of its arguments, and therefore declare the interface section for compareFunc
. Note the first argument of compareFunc
is of type person_list
. (As you might tell, person_list
is like TStringList
in Delphi's VCL.)
The compilation cannot proceed. The error messages are:
[root@localhost new]# ifort -c lib1.f90
lib1.f90(26): error #6457: This derived type name has not been declared. [PERSON_LIST]
TYPE(person_list) :: persons ! error #6457: This derived type name has not been declared. [PERSON_LIST]
-------------------------^
lib1.f90(23): error #6404: This name does not have a type, and must have an explicit type. [PERSONS]
FUNCTION compareFunc(persons, index1, index2) ! error #6404: This name does not have a type, and must have an explicit type. [PERSONS]
-------------------------------------^
compilation aborted for lib1.f90 (code 1)
The error messages seem to indicate a circular reference between modules? I am therefore wondering how to declare the interface section for a procedure argument, which in turn references to a user-derived type of the same module? Any insights will be appreciated!
PS: The reason to try this module is the preference of OO programing style. The reason to try fortran is a big code base.
PS: The compiler is Intel Fortran Compiler, and the version is as the follows:
[root@localhost new]# ifort --version
ifort (IFORT) 12.1.0 20111011
Copyright (C) 1985-2011 Intel Corporation. All rights reserved.
MODULE lib1
TYPE person_list
CONTAINS
PROCEDURE, PASS :: compare_persons
END TYPE
CONTAINS
FUNCTION compare_persons(this, index1, index2, compareFunc)
IMPLICIT NONE
INTEGER :: compare_persons
CLASS(person_list) :: this
INTEGER, INTENT(IN) :: index1
INTEGER, INTENT(IN) :: index2
INTERFACE
FUNCTION compareFunc(persons, index1, index2) ! error #6404: This name does not have a type, and must have an explicit type. [PERSONS]
IMPLICIT NONE
INTEGER :: compareFunc
TYPE(person_list) :: persons ! error #6457: This derived type name has not been declared. [PERSON_LIST]
INTEGER :: index1
INTEGER :: index2
END FUNCTION compareFunc
END INTERFACE
compare_persons = compareFunc(this, index1, index2)
END FUNCTION compare_persons
END MODULE lib1
tpg2114
figures out the solution!MODULE lib1
TYPE person_list
CONTAINS
PROCEDURE, PASS :: compare_persons
END TYPE
INTERFACE
FUNCTION CompareFuncInterface(persons, index1, index2)
IMPORT person_list
IMPLICIT NONE
INTEGER :: CompareFuncInterface
TYPE(person_list), INTENT(IN) :: persons
INTEGER, INTENT(IN) :: index1
INTEGER, INTENT(IN) :: index2
END FUNCTION CompareFuncInterface
END INTERFACE
CONTAINS
FUNCTION compare_persons(this, index1, index2, compareFunc)
IMPLICIT NONE
INTEGER :: compare_persons
CLASS(person_list), INTENT(IN) :: this
INTEGER, INTENT(IN) :: index1
INTEGER, INTENT(IN) :: index2
PROCEDURE (CompareFuncInterface) :: compareFunc
compare_persons = compareFunc(this, index1, index2)
END FUNCTION compare_persons
END MODULE lib1
Upvotes: 1
Views: 2126
Reputation: 15100
Okay, I figured it out:
MODULE lib1
TYPE :: persons
CONTAINS
PROCEDURE, PASS :: compare_persons
END TYPE persons
INTERFACE
INTEGER FUNCTION compareFunc_interface(personsIn, index1, index2)
IMPORT persons
IMPLICIT NONE
TYPE(persons), INTENT(IN) :: personsIn
INTEGER, INTENT(IN) :: index1
INTEGER, INTENT(IN) :: index2
END FUNCTION compareFunc_interface
END INTERFACE
CONTAINS
FUNCTION compare_persons(this, index1, index2, compareFunc)
IMPLICIT NONE
INTEGER :: compare_persons
CLASS(persons) :: this
INTEGER :: index1
INTEGER :: index2
PROCEDURE(compareFunc_interface) :: compareFunc
END FUNCTION compare_persons
END MODULE lib1
From the 2003 standard, the IMPORT
statement brings a definition from the host scoping unit to the local scoping unit. If you were using something from a different module, the INTERFACE
would need a USE
statement. But since you are importing from the higher up scoping unit, you use IMPORT
and a list of the things you would like to bring into that scope
Edit
Also note, I added PASS
to the declaration of the type-bound procedure. Although not required (because this is the default action), I prefer to always put PASS
or NOPASS
so that the intention is always explicit. This helps both the programmer (making sure they do what they think they are doing) and anybody who reads the code.
Upvotes: 5