我目前正在尝试将我的代码拆分为模块和子模块。我有许多将过程作为参数的过程,在某些情况下,这些过程参数的参数是多态的。将这些过程拆分为子模块时,我的代码不再编译。
作为一个最小的工作示例,我有一个模块文件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.0
thenfoo
编译,则可以自行编译并运行良好,但尝试编译bar
会出现错误
26 | call lambda(input)
| 1
Error: Explicit interface required for polymorphic argument at (1)
如果我改为编译,ifort 2021.1
我会收到编译时警告(对于foo
和bar
)
warning #8889: Explicit declaration of the EXTERNAL attribute is required. [LAMBDA]
call lambda(input)
-----------^
然后是链接器错误(对于foo
和bar
)
m_sub.f90.o: In function `m_mp_foo_':
undefined reference to `lambda_'
据我所知,我正在做的是有效的 Fortran。那么我是否看到编译器错误/未实现的功能?还是我试图做一些标准不允许的事情?