函数或子例程中的 Fortran 和接口块

Fortran and interface blocks in functions or subroutines

我想编写一个模块,它将根据 "user" 在不同文件中提供的函数类型执行一些操作。该函数将作为该模块的 "execute(...)" 子例程的参数传递。这基本上是我想要获得的,但我不知道这是否可能,我应该如何正确地做到这一点。

module mod1
contains
subroutine execute(func)
 interface func
 real function func1(a,b)
    real a,b
 end function 
 real function func2(a,b,c)
    real a,b,c
 end function 
 ! more similar functions here
 end interface func

   ! -------------------
   ! here some how choose between func1 or func2
   ! and do the calculations
   if(func1) then ...
   else if(func2) ...
   ! -------------------
endsubroutine execute 
endmodule mod1
------------------------------------------
program
use mod1
call execute(test) 
contains
real function test(a,b)
real a,b
test = a + b
end function
end program

我知道这段代码无法编译,但这只是一个草图。目前,对我来说,这个问题唯一丑陋的解决方案是为执行子例程编写许多替代方案,即 execute_1、execute_2 并且根据测试函数,用户必须选择适当的 execute_X 函数.

这个问题有更好的解决方案吗?

提前致谢。 KK

根据示例来源稍微猜测一下您的意图,您的问题是您想要一个可能具有不同特征的虚拟过程 - 例如参数的数量。

我不推荐这样做,但 Fortran 允许虚拟过程具有隐式接口 - 您可以只为 func 虚拟过程提供外部属性,然后由程序员负责确保通过虚拟程序引用的性质与实际程序的接口一致。这种方法可能无法使用需要显式接口的语言工具。

subroutine execute(func)
  real, external :: func
  !...
  if (some_condition) then
    x = func(a, b)
  else
    x = func(a, b, c)
  end if

如果您希望虚拟过程具有显式接口,那么您可以使用可选参数。

module mod1
contains
  subroutine execute(func1, func2)
    interface
      real function func1(a,b)
        real a,b
      end function func1
      real function func2(a,b,c)
        real a,b,c
      end function func2
    end interface
    optional :: func1, func2

    !...

    if (present(func1)) x = func1(a, b)
    if (present(func2)) x = func2(a, b, c)
  end subroutine execute
end module mod1

program p
  use mod1
  call execute(func1=test) 
contains
  real function test(a,b)
    real a,b
    test = a + b
  end function
end program p

此问题的更通用的解决方案可能是通过派生类型的绑定来调用过程 - 过程的调用始终使用相同的接口,但随后可以使用派生类型的组件将附加信息传递给过程类型。

您也可以将接口放在模块头中,并像这样为 func1 和 func2 使用 procedure 属性。如果您想在别处使用它们,这很有用,因为您只在一个地方定义它们。

module mod1

abstract interface
  real function f1(a,b)
    real,intent(in) :: a,b
  end function f1
  real function f2(a,b,c)
    real,intent(in) :: a,b,c
  end function f2  
end interface

contains

  subroutine execute(func1, func2)
  procedure(f1),optional :: func1
  procedure(f2),optional :: func2

  !...

  if (present(func1)) x = func1(a, b)
  if (present(func2)) x = func2(a, b, c)
  end subroutine execute

end module mod1