使用模块但在模块外部的子程序,也通过接口在模块中使用

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

有几种方法可以解决这个问题:

对于大型项目来说有点麻烦。

还有其他方法吗?

除了使用 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 不再是外部子例程,因此其他引用可能需要修复。