Compiler: ifort version 12.1.5
I'm writing some Fortran code and I'd like to make use of some F2003 OOP features, but I'm hitting some stumbling blocks. Paring down the example, I wish to have two derived types A and B, each of which have a pointer to instances of the other. In Fortran, circular dependencies between modules are explicitly disallowed, so these two types would have to reside in the same module. This compiles:
module testModule
implicit none
type A
type(B),pointer :: b1
end type A
type B
type(A),pointer :: a1
end type B
contains
[some possibly type-bound procedures]
end module
Now, I want to implement some constructors for these types, and try this code:
module testModule
implicit none
type A
type(B),pointer :: b1
end type A
interface A
module procedure A_ctor
end interface
type B
type(A),pointer :: a1
end type B
interface B
module procedure B_ctor
end interface
contains
function A_ctor()
type(A),target :: A_ctor
end function
function B_ctor()
type(B),target :: B_ctor
end function
end module
Now, this doesn't compile, throwing an error
This is not a derived type name. [B]
on line 5 above. Why does adding the interfaces throw an error? How does one handle circular dependencies in derived types in Fortran, as one would use a forward class declaration in C++?
Even though 2003 sounds long ago, implementation of fortran 2003 is still an ongoing process in most compilers. There may very well still be omissions or bugs in the handling of new features.
Check with the support team of your compiler if this is a known issue, and, if so, if there is a newer version that fixes this.
As supporting - though not conclusive - evidence that this code is standard conforming, gfortran compiles it without error (just two warnings about not setting a return value for the functions).
Your code is correct Fortran 2003. You are handling the circular type dependency in the correct way. The compiler is in error.
I have experienced and seen others report issues with ifort 12.1.5 and programmer overrides of structure constructors (where there is a generic interface to a function that has a derived type result, with the interface having the same name as the derived type - as you have here). A workaround for this situation to rename the generic interface (and subsequent references) for the constructor function to a name different from the derived type.