如果我们有三个具有不同派生类型的不同文件,
MyTypeMod.f90:
MODULE MyTypeMod
TYPE, ABSTRACT :: MyType
INTEGER :: Num
END TYPE MyType
CONTAINS
END MODULE MyTypeModMyType1Mod.f90
MODULE MyType1Mod
USE MyTypeMod, ONLY : MyType
USE MyType2Mod, ONLY : MyType2
IMPLICIT NONE
TYPE, EXTENDS(MyType) :: MyType1
CONTAINS
PROCEDURE :: Type1EqualsType2
GENERIC :: ASSIGNMENT(=) => Type1EqualsType2
END TYPE MyType1
CONTAINS
SUBROUTINE Type1EqualsType2(Type1, Type2)
TYPE(MyType1), INTENT(OUT) :: Type1
TYPE(MyType2), INTENT(IN) :: Type2
Type1%Num = Type2%Num
END SUBROUTINE Type1EqualsType2
END MODULE MyType1ModMyType2Mod.f90
MODULE MyType1Mod
USE MyTypeMod, ONLY : MyType
USE MyType1Mod, ONLY : MyType1
IMPLICIT NONE
TYPE, EXTENDS(MyType) :: MyType2
CONTAINS
PROCEDURE :: Type2EqualsType1
GENERIC :: ASSIGNMENT(=) => Type2EqualsType1
END TYPE MyType2
CONTAINS
SUBROUTINE Type2EqualsType1(Type2, Type1)
TYPE(MyType2), INTENT(OUT) :: Type2
TYPE(MyType1), INTENT(IN) :: Type1
Type2%Num = Type1%Num
END SUBROUTINE Type2EqualsType1
END MODULE MyType2Mod在这里,在这种情况下,由于模块文件相互依赖,我无法编译程序。我能用SubModules来解决这个问题吗?
发布于 2021-10-21 12:23:04
不幸的是,不,您不能完全按照您的要求使用子模块。这是因为两个函数Type1EqualsType2和Type2EqualsType1在其函数接口中都需要MyType1和MyType2。即使您使用子模块,这两个函数都必须在各自的模块中具有接口,因此循环依赖关系仍然存在。
然而,有几种可能的解决办法:
选择类型
这两个函数的intent(in)参数都可以是class(MyType),并且只能使用select type语句进行类型解析。这将允许您将函数定义移动到子模块并解析循环依赖,但也意味着您必须处理将扩展MyType的不同类型传递给函数的情况。而且,select type可能会慢一点,这取决于您的用例。
用于此的代码如下所示:
MODULE MyTypeMod
IMPLICIT NONE
TYPE, ABSTRACT :: MyType
INTEGER :: Num
END TYPE MyType
END MODULE MyTypeMod
MODULE MyType1Mod
USE MyTypeMod, ONLY : MyType
IMPLICIT NONE
TYPE, EXTENDS(MyType) :: MyType1
CONTAINS
PROCEDURE :: Type1EqualsType2
GENERIC :: ASSIGNMENT(=) => Type1EqualsType2
END TYPE
interface
module SUBROUTINE Type1EqualsType2(this, input)
TYPE(MyType1), INTENT(OUT) :: this
class(MyType), INTENT(IN) :: input
END SUBROUTINE
end interface
END MODULE
MODULE MyType2Mod
USE MyTypeMod, ONLY : MyType
IMPLICIT NONE
TYPE, EXTENDS(MyType) :: MyType2
CONTAINS
PROCEDURE :: Type2EqualsType1
GENERIC :: ASSIGNMENT(=) => Type2EqualsType1
END TYPE
interface
module SUBROUTINE Type2EqualsType1(this, input)
TYPE(MyType2), INTENT(OUT) :: this
class(MyType), INTENT(IN) :: input
END SUBROUTINE
end interface
END MODULE
submodule (MyType1Mod) MyType1Submod
use MyType2Mod, only : MyType2
implicit none
contains
module procedure MyType1EqualsMyType2
select type(input); type is(MyType1)
this%Num = input%Num
type is(MyType2)
this%Num = input%Num
class default
! Some kind of error handling goes here.
end select
end procedure
end submodule
submodule (MyType2Mod) MyType2Submod
use MyType1Mod, only : MyType1
implicit none
contains
module procedure MyType2EqualsMyType1
select type(input); type is(MyType1)
this%Num = input%Num
type is(MyType2)
this%Num = input%Num
class default
! Some kind of error handling goes here.
end select
end procedure
end submodule通用程序
您可以将类型绑定的assignment(=)定义替换为泛型assignment(=)定义。这避免了运行时多态,但意味着您必须在一个新模块中定义赋值。
这看起来应该是:
MODULE MyTypeMod
IMPLICIT NONE
TYPE, ABSTRACT :: MyType
INTEGER :: Num
END TYPE MyType
END MODULE MyTypeMod
MODULE MyType1Mod
USE MyTypeMod, ONLY : MyType
IMPLICIT NONE
TYPE, EXTENDS(MyType) :: MyType1
END TYPE
END MODULE
MODULE MyType2Mod
USE MyTypeMod, ONLY : MyType
IMPLICIT NONE
TYPE, EXTENDS(MyType) :: MyType2
END TYPE
END MODULE
module MyEqualsMod
use MyType1Mod : only MyType1
use MyType2Mod : only MyType2
implicit none
interface assignment(=)
module procedure MyType1EqualsMyType2
module procedure MyType2EqualsMyType1
end interface
contains
subroutine MyType1EqualsMyType2(this,input)
type(MyType1), intent(out) :: this
type(MyType2), intent(in) :: input
this%Num = input%Num
end subroutine
subroutine MyType2EqualsMyType1(this,input)
type(MyType2), intent(out) :: this
type(MyType1), intent(in) :: input
this%Num = input%Num
end subroutine
end modulehttps://stackoverflow.com/questions/69655818
复制相似问题