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.
The code sample is:
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
Okay, I figured it out:
From the 2003 standard, the
IMPORTstatement brings a definition from the host scoping unit to the local scoping unit. If you were using something from a different module, theINTERFACEwould need aUSEstatement. But since you are importing from the higher up scoping unit, you useIMPORTand a list of the things you would like to bring into that scopeEdit
Also note, I added
PASSto the declaration of the type-bound procedure. Although not required (because this is the default action), I prefer to always putPASSorNOPASSso 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.