Fortran中的程序指针 [英] Procedural pointer in fortran
本文介绍了Fortran中的程序指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
假设我有以下指向单参数的双精度函数的抽象接口
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)
的指针,即指向a
和b
的固定值的f
的指针,这可以被视为只有一个参数的函数,即dp_func
类型?
最终,我希望能够编写类似的内容
p=>f(myA, myB, )
y=p(x)
下面的注释表明function closure不是Fortran标准的一部分,包装函数可能是它的解决方案。但是,包装器必须初始化,这会导致最终用户可能忘记调用初始化式。如何才能以干净透明的方式做到这一点?
编辑 在发布这个问题并用谷歌搜索";闭包和Fortran";之后,我找到了这个例子
我以图片的形式呈现,以强调突出。这是在一门在线课程中介绍的。但我怀疑这种隐式参数设置是否是良好的编程实践。事实上,像本例中的z
这样的悬空变量就是错误的完美来源!
推荐答案
您陈述了以下内容: 但是,包装必须初始化,这会导致最终用户可能忘记调用初始化式。如何才能以干净透明的方式做到这一点?...
以下可能是一个解决方案。 它仍需要初始化,但如果用户尚未执行此操作,则将引发错误。
我定义了一个处理函数指针的类型closure
。
! file closure.f90
module closure_m
implicit none
type closure
private
procedure(f1), pointer, nopass :: f1ptr => null()
procedure(f3), pointer, nopass :: f3ptr => null()
real :: a, b
contains
generic :: init => closure_init_f1, closure_init_f3
!! this way by calling obj%init one can call either of the two closure_init_fX procedures
procedure :: exec => closure_exec
procedure :: closure_init_f1, closure_init_f3
end type
abstract interface
real function f1(x)
real, intent(in) :: x
end function
real function f3(a, b, x)
real, intent(in) :: a, b, x
end function
end interface
contains
subroutine closure_init_f1(this, f)
class(closure), intent(out) :: this
procedure(f1) :: f
this%f1ptr => f
this%f3ptr => null()
end subroutine
subroutine closure_init_f3(this, f, a, b)
class(closure), intent(out) :: this
procedure(f3) :: f
real, intent(in) :: a, b
this%f1ptr => null()
this%f3ptr => f
this%a = a
this%b = b
end subroutine
real function closure_exec(this, x) result(y)
class(closure), intent(in) :: this
real, intent(in) :: x
if (associated(this%f1ptr)) then
y = this%f1ptr(x)
else if (associated(this%f3ptr)) then
y = this%f3ptr(this%a, this%b, x)
else
error stop "Initialize the object (call init) before computing values (call exec)!"
end if
end function
end module
关于行class(closure), intent(out) :: this
:
这是为Fortran类型编写初始值设定项的标准方法。
请注意,它是class
而不是type
,这使得this
成为类型绑定过程所需的多态。
我稍微调整了您的函数模块(更改了数据类型)
! file fns.f90
module fns_m
contains
real function f(a, b, x)
real, intent(in) :: a, b, x
f = (a-b)*x
end function
real function g(x)
real, intent(in) :: x
g = x**2
end function
end module
示例程序
! file a.f90
program main
use closure_m
use fns_m
implicit none
type(closure) :: c1, c2
call c1%init(g)
print *, c1%exec(2.0)
call c1%init(f, 1.0, 2.0)
print *, c1%exec(2.0)
call c2%init(f, 1.0, -2.0)
print *, c2%exec(3.0)
end program
输出示例
$ gfortran closure.f90 fns.f90 a.f90 && ./a.out
4.00000000
-2.00000000
9.00000000
这篇关于Fortran中的程序指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文