2

我目前正在尝试将我的代码拆分为模块和子模块。我有许多将过程作为参数的过程,在某些情况下,这些过程参数的参数是多态的。将这些过程拆分为子模块时,我的代码不再编译。

作为一个最小的工作示例,我有一个模块文件m.f90

module m
  implicit none
  
  ! Interface to `foo`, which simply calls `lambda(input)`.
  interface foo
    module subroutine foo(input,lambda)
      implicit none
      
      class(*), intent(in)  :: input
      procedure(TestLambda) :: lambda
    end subroutine
  end interface
  
  ! Interface to `bar`, which simply calls `lambda(input)`
  interface bar
    module subroutine bar(input,lambda)
      implicit none
      
      class(*), intent(in)  :: input
      procedure(TestLambda) :: lambda
    end subroutine
  end interface
  
  ! Interface defining the `lambda` arguments of `foo` and `bar`.
  interface TestLambda
    subroutine TestLambda(input)
      implicit none
      
      class(*), intent(in) :: input
    end subroutine
  end interface

end module

和一个子模块文件m_sub.f90

submodule (m) m_sub
contains

  ! Implementation of `foo`.
  module subroutine foo(input,lambda)
    implicit none

    class(*), intent(in)  :: input
    procedure(TestLambda) :: lambda
    
    call lambda(input)
  end subroutine
  
  ! Implementation of `bar`.
  ! This is identical to `foo`, except that the interface is implicit.
  module procedure bar
    call lambda(input)
  end procedure

end submodule

并且,为了完整起见,一个程序文件main.f90

program test
  use m
  implicit none
  
  write(*,*) 'Hello, World!'
  call test_lambda(1)
  call foo(1, test_lambda)
  call bar(1, test_lambda)
contains
  subroutine test_lambda(input)
    implicit none
    
    class(*), intent(in) :: input
    
    write(*,*) 'Hello, World!'
  end subroutine
end program

我正在使用 CMake 编译它,并带有一个CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
enable_language(Fortran)
set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/mod/)

if("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "GNU")
  set(CMAKE_Fortran_FLAGS "-W -Wall -Wextra -pedantic -fcheck=all -std=f2008")
elseif("${CMAKE_Fortran_COMPILER_ID}" STREQUAL "Intel")
  set(CMAKE_Fortran_FLAGS "-stand f08 -warn all")
endif()

project(test)
add_executable(test main.f90 m.f90 m_sub.f90)

如果我使用gfortran 10.1.0thenfoo编译,则可以自行编译并运行良好,但尝试编译bar会出现错误

   26 |       call lambda(input)
      |                  1
Error: Explicit interface required for polymorphic argument at (1)

如果我改为编译,ifort 2021.1我会收到编译时警告(对于foobar

 warning #8889: Explicit declaration of the EXTERNAL attribute is required.   [LAMBDA]
      call lambda(input)
-----------^

然后是链接器错误(对于foobar

m_sub.f90.o: In function `m_mp_foo_':
undefined reference to `lambda_'

据我所知,我正在做的是有效的 Fortran。那么我是否看到编译器错误/未实现的功能?还是我试图做一些标准不允许的事情?

4

0 回答 0