fortran - fortran中的过程指针

标签 fortran function-pointers

假设我对单参数的 double 函数有以下抽象接口(interface)

module abstract

  abstract interface
     function dp_func (x)
       double precision, intent(in) :: x
       double precision :: dp_func
     end function dp_func
  end interface

end module abstract
在不同的模块中,我定义了两个函数,一个简单的 g dp_func 类型的还有一个更复杂的 f
module fns

 contains
 double precision function f(a,b,x)
   double precision, intent(in)::a,b,x
   f=(a-b)*x 
 end function f

 double precision function g(x)
   double precision, intent(in)::x
   g=x**2 
 end function g
end module fns
现在指向 g 的指针可以创建如下
program main
use abstract,fns
procedure(dp_func), pointer :: p
double precision::x=1.0D0, myA=1.D2, myB=1.D1, y
p => g
y=p(x)
end program main
但是如何创建指向 f(myA,myB,x) 的指针? ,即到 f固定值为 ab , 可以看作是只有 1 个参数的函数,即 dp_func类型?
最后的结果是我希望能够写出类似的东西
p=>f(myA, myB, )
y=p(x)
下面的评论建议 function closure不是 fortran 标准的一部分,并且包装函数将是它的可能解决方案。但是,必须初始化包装器,这会带来一些最终用户可能忘记调用初始化器的机会。如何以一种干净透明的方式做到这一点?
编辑
在发布这个问题并使用“closure and fortran”进行谷歌搜索后,我找到了这个例子
enter image description here
我以图片形式呈现以强调突出显示。这是在线类(class)中介绍的。但我怀疑这种隐式参数设置是一种很好的编程习惯。事实上,像 z 这样的悬空变量在这个例子中是完美的错误来源!

最佳答案

您可以使用内部函数来包装您的函数,例如

program main
  use abstract
  use fns
  implicit none
  
  procedure(dp_func), pointer :: p
  double precision :: x, myA, myB, y
  
  x = 1.0D0
  myA = 1.D2
  myB = 1.D1
  
  p => g
  y=p(x)
  
  p => f2
  y = p(x) ! Calls f(1.D2, 1.D1, x)
  
  myA = 1.D3
  myB = 1.D2
  
  y = p(x) ! Calls f(1.D3, 1.D2, x)
contains
  double precision function f2(x)
    double precision, intent(in) :: x
    write(*,*) myA, myB
    f2 = f(myA,myB,x)
  end function
end program main
给定范围内的内部函数可以使用该范围内的变量,因此它们可以像闭包一样工作。myA 的隐式使用和 myB在内部函数f2很可能是编程错误的来源,但是,提供 f2 的范围仍在范围内,此行为与 lambda 相同其他语言中的函数,例如等效的 python lambda:
f2 = lambda x: f(myA,myB,x)
正如@vladimirF 所指出的,一旦f2 的范围超出范围(例如,如果存储了指向 f2 的指针并且声明了 f2 的过程返回)任何指向 f2 的指针将失效。这可以在这段代码中看到:
module bad
  use abstract
  use fns
  implicit none
contains

function bad_pointer() result(output)
  procedure(dp_func), pointer :: output
  
  double precision :: myA,myB
  
  myA = 1.D2
  myB = 1.D1
  
  output => f2
contains
  double precision function f2(x)
    double precision, intent(in) :: x
    write(*,*) myA, myB
    f2 = f(myA,myB,x)
  end function
end function

end module

program main
  use abstract
  use fns
  use bad
  implicit none
  
  procedure(dp_func), pointer :: p
  double precision :: y,x
  
  p => bad_pointer()
  x = 1.D0
  y = p(x)
end program
注:对于这种简单的情况,上面的代码可能运行良好,但它依赖于未定义的行为,因此不应使用。

关于fortran - fortran中的过程指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67161321/

相关文章:

fortran - 如何为 'allocate' 编写包装器

fortran - 在 fortran 中生成序列数组

c - 什么时候在函数指针中使用 "&"运算符?

fortran - 在fortran程序中调用METIS API(C语言编写)

matrix - Fortran中多线程矩阵的转置

c++ - ISO C++ 禁止在指向函数的指针和指向对象的指针之间进行转换

c++ - 将指针传递给指向函数的指针时出现段错误

c++ - 为什么 C++ 函数的地址总是 True?

fortran - Fortran 中的 PGI 编译错误 : "forward reference to function"

函数返回函数指针的 C 语法