繁体   English   中英

在 Fortran 中是否可以在类型绑定过程中在运行时分配过程名称?

[英]Is it possible in Fortran to assign procedure name at run time in a type bound procedure?

我发现了类型绑定过程,并且想知道如何使用它们。 我有按预期工作的代码:

module utils
implicit none
type TypeParam
  integer :: val
  contains
    procedure :: initval  => initI
    procedure :: writeval => writeI
end type TypeParam
contains
!---------------------------
  subroutine initI(this,val)
  class(TypeParam),intent(inout)::this
  integer,intent(in) :: val
  
  this%val=val

  end subroutine initI
!---------------------------  
  subroutine writeI(this)
  class(TypeParam),intent(inout)::this
  
  print*,this%val

  end subroutine writeI      
!---------------------------  
end module utils

program testtypebound
use utils
implicit none
type(TypeParam) :: TP(2)

call TP(1)%initval(3)
call TP(2)%initval(5)
call TP(1)%writeval() ! Returns 3
call TP(2)%writeval() ! Returns 5

end program testtypebound

现在我不知道如何在运行时分配 initval 和 writeval,如果它有任何意义的话。 让它们指向 null() 并在主程序中将它们分配为 TP(1)%initval=>othersubroutine。

下面的代码不使用类型绑定过程,它执行我想要的操作,但不确定它是否是通往 go 的方式。第二种方法是否有任何缺陷?

非常感谢

module utils
implicit none
type TypeParam
  integer :: val
  procedure(InitValInteger),  pointer :: initval  => null()
  procedure(WriteValInteger), pointer :: writeval => null()
end type TypeParam

interface
  subroutine InitValInteger(this,val)
  import TypeParam
  class(TypeParam),intent(inout)::this
  integer,intent(in) :: val
  end subroutine InitValInteger

  subroutine WriteValInteger(this)
  import TypeParam  
  class(TypeParam),intent(inout)::this  
  end subroutine WriteValInteger  
end interface

contains
!---------------------------
  subroutine initI(this,val)
  class(TypeParam),intent(inout)::this
  integer,intent(in) :: val
  
  this%val=val

  end subroutine initI
!---------------------------  
  subroutine writeI(this)
  class(TypeParam),intent(inout)::this
  
  print*,this%val

  end subroutine writeI      
!---------------------------  
end module utils

program testtypebound
use utils
implicit none
type(TypeParam) :: TP(2)

TP(1)%initval =>initI
TP(1)%writeval=>writeI
TP(2)%initval =>initI
TP(2)%writeval=>writeI
call TP(1)%initval(3) 
call TP(2)%initval(5)
call TP(1)%writeval() ! Returns 3
call TP(2)%writeval() ! Returns 5

end program testtypebound

澄清

正如评论中指出的那样,前面的示例可能没有用。 这是我认为可以做我想要的并且可以扩展到我的真实代码的代码:

module utils
implicit none
type TypeParam
  integer :: val
  procedure(UseValue),  pointer :: useval  => null()
end type TypeParam

interface
  real*8 function UseValue(this,i)
  import TypeParam
  class(TypeParam),intent(inout)::this
  integer,intent(in) :: i
  end function UseValue
end interface
contains
!---------------------------
  real*8 function useval1(this,i)
  class(TypeParam),intent(inout)::this
  integer,intent(in) :: i
  
  useval1=this%val+i

  end function useval1
!---------------------------
  real*8 function useval2(this,i)
  class(TypeParam),intent(inout)::this
  integer,intent(in) :: i
  
  useval2=this%val**2+i

  end function useval2         
!---------------------------  
end module utils

program testtypebound
use utils
implicit none
integer :: i
type(TypeParam) :: TP

write(*,*) "Enter version 1 or 2"
read(*,*) i

if(i==1)then
  TP%val=2
  TP%useval =>useval1
elseif(i==2)then  
  TP%val=1
  TP%useval =>useval2
else
  write(*,*) "Version unknown (1 or 2)"
  stop  
endif
print*, TP%useval(2) ! Returns 4 if i=1 and 3 if i=2

end program testtypebound

但在我开始实施之前,这段代码是否有缺点、缺陷? 可以使用类型绑定过程使其更简单/更紧凑吗? 在现实生活中,TP 将是一个数组,这样数组的每个组件将根据用户输入保存不同的过程。

类型绑定过程“绑定到派生类型并通过该类型的 object 引用”(Fortran 2018,3.112.6)。 绑定到一个类型而不是object意味着相同类型的两个对象产生相同的引用。 (此外,类型的定义在执行期间不能更改。)

过程指针组件不同:它是类型的组件,类型的每个 object 实例都可以有自己的值,对于变量,其值可以在执行期间更改。

哪种机制最适合用例取决于需要什么。 如果您希望相同类型的两个对象解析为不同的过程引用,或者希望引用的过程在执行过程中发生变化,您将使用过程指针组件。

过程指针可以不关联,并且类型绑定过程没有等效的 state。 这意味着您有责任确保call a%s()具有与目标关联的s过程指针组件指针,但也允许您执行类似if (ASSOCIATED(a%s))...逻辑(如果它是定义的关联状态)。 您还负责确保它始终指向您希望它指向的位置(另请注意,不能保护组件)并且为了方便起见,您最终可能会编写一个结构构造函数。

同样,过程指针组件可以以绑定名称不能使用的方式使用: call run(a%s)允许用于过程指针组件,但不允许用于类型绑定过程。

也就是说,基于运行时条件的引用用例甚至可以使用类型绑定过程来解决:

type t
  logical :: use_a = .TRUE.
 contains
  procedure :: selector
end type t

selector是一个包装器

subroutine selector(this, val)
  class(t), intent(in) :: this
  integer, intent(in) :: val

  if (this%use_a) then
    call A(this, val)
  else
    call B(this, val)
  end if
end subroutine selector

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM