使用模块但在模块外部的子程序,也通过接口在模块中使用
subroutine using module but is outside module and also used in module through an interface
当我在模块外有一个子例程但通过“指针赋值”使用并且子例程通过接口定义但真正的子例程在单独的文件中并使用模块时我得到编译器错误.
所以当我有以下 Fortran 代码时:
module test_mod_a
save
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
subroutine test_subr_a(this)
import test_type_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
和
subroutine test_subr_a(this)
use test_mod_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
当我给出命令时(gfortran 版本 9.3.0):
gfortran -c test_a.f90
gfortran -c test_a_subr.f90
我收到编译器错误:
test_a_subr.f90:3:6:
3 | use test_mod_a
| 1
Error: ‘test_subr_a’ of module ‘test_mod_a’, imported at (1), is also the name of the current program unit
有几种方法可以解决这个问题:
- 将
!use test_mod_a
替换为 !use test_mod_a, only : test_type_a
- 在模块中包含子例程(并在子例程中丢弃
use
语句并在模块中丢弃 interface
对于大型项目来说有点麻烦。
还有其他方法吗?
除了使用 only
(不包括过程名称)之外,还有另外两种避免标识符重用的技术:
private test_subr_a
在模块中
- 在
use test_mod_a, self_iface => test_subr_a
的子例程中使用重命名
然而,从结构的外观来看,似乎 test_subr_a
的意图确实是像模块子例程,但不是出于以下两个原因之一:
- 对旧程序进行了增量开发,现在希望以“现代”方式使用外部子例程
- 由于文件大小的原因,子程序的实现被拆分出来,避免编译级联,实现的保密性
通过以重要方式更改代码的奢侈,人们可以处理这些问题。
出于第一个原因,可以继续将子例程移动到模块中,并承担必须更新外部子例程的其他引用的痛苦。正如问题中提到的。
第二个原因,可以考虑submodules:
module test_mod_a
implicit none
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
submodule(test_mod_a) implementation_a
implicit none
contains
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end submodule implementation_a
同样,test_subr_a
不再是外部子例程,因此其他引用可能需要修复。
当我在模块外有一个子例程但通过“指针赋值”使用并且子例程通过接口定义但真正的子例程在单独的文件中并使用模块时我得到编译器错误.
所以当我有以下 Fortran 代码时:
module test_mod_a
save
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
subroutine test_subr_a(this)
import test_type_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
和
subroutine test_subr_a(this)
use test_mod_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
当我给出命令时(gfortran 版本 9.3.0):
gfortran -c test_a.f90
gfortran -c test_a_subr.f90
我收到编译器错误:
test_a_subr.f90:3:6:
3 | use test_mod_a
| 1
Error: ‘test_subr_a’ of module ‘test_mod_a’, imported at (1), is also the name of the current program unit
有几种方法可以解决这个问题:
- 将
!use test_mod_a
替换为!use test_mod_a, only : test_type_a
- 在模块中包含子例程(并在子例程中丢弃
use
语句并在模块中丢弃interface
对于大型项目来说有点麻烦。
还有其他方法吗?
除了使用 only
(不包括过程名称)之外,还有另外两种避免标识符重用的技术:
private test_subr_a
在模块中- 在
use test_mod_a, self_iface => test_subr_a
的子例程中使用重命名
然而,从结构的外观来看,似乎 test_subr_a
的意图确实是像模块子例程,但不是出于以下两个原因之一:
- 对旧程序进行了增量开发,现在希望以“现代”方式使用外部子例程
- 由于文件大小的原因,子程序的实现被拆分出来,避免编译级联,实现的保密性
通过以重要方式更改代码的奢侈,人们可以处理这些问题。
出于第一个原因,可以继续将子例程移动到模块中,并承担必须更新外部子例程的其他引用的痛苦。正如问题中提到的。
第二个原因,可以考虑submodules:
module test_mod_a
implicit none
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
submodule(test_mod_a) implementation_a
implicit none
contains
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end submodule implementation_a
同样,test_subr_a
不再是外部子例程,因此其他引用可能需要修复。