generics - 如何直接使用泛型函数定义一个新的Fortran过程?

标签 generics fortran

其实我想问的不是解决问题,而是变得更熟练。

假设我们有一个类型 A,例如:

Type A
private
    (some variant)
contains
(some procedures)
generic::f=>....     
  ! we assume the inteface is f(input)
  !  real or integer or complex :: input
endtype

其中f包含许多子例程。

现在我有另一种类型 B,其中使用了 A

Type B
private
    type(A)::oA
    ...
contains
    f2       
    ! we assume the interface is f2(otherinput,input)
    !  real :: otherinput
    !  real or integer or complex :: input
end type

现在我想定义子例程f2,其中将调用f。除了已知类型 otherinput 之外,我们还有一个多重类型 input (我不确定我的陈述是否正确,但无论如何)。

突然我意识到我需要根据输入的不同类型定义很多子程序f2_1,f2_2,...。但这是愚蠢的,因为在 f 中已经考虑了这类事情。如何避免这种烦恼?

最佳答案

虽然不是很优雅,但通过 class(*) 接收参数“input”并显式选择其类型来调用泛型函数 f 怎么样?例如,

module test_m
    implicit none

    type A_t
    contains
        procedure :: f_int
        procedure :: f_real
        generic :: f => f_int, f_real
    endtype

    type B_t
        type(A_t) :: A
    contains
        procedure :: g
    endtype

contains

    subroutine f_int( me, n )
        class(A_t) :: me
        integer :: n
        print *, "f_int  : ", n
    endsubroutine

    subroutine f_real( me, x )
        class(A_t) :: me
        real :: x
        print *, "f_real :", x
    endsubroutine

    subroutine g( me, str, arg )    ! 'arg' <-> 'input'
        class(B_t) :: me
        character(*) :: str
        class(*) :: arg
        print *, "g : ", str

        select type ( arg )
        type is ( integer )
            call me % A % f( arg )  
        type is ( real )
            call me % A % f( arg )
        endselect
    endsubroutine

end module

program main
    use test_m
    implicit none
    type(A_t) :: A
    type(B_t) :: B

    call A % f( 100 )
    call A % f( 1.23 )

    call B % g( "hi", -100 )
    call B % g( "yo", -1.23 )
end

gfortran-4.8 和 7.1 的结果:

 f_int  :          100
 f_real :   1.23000002    
 g : hi
 f_int  :         -100
 g : yo
 f_real :  -1.23000002

但是上面的代码与从 select type 中调用特定函数(f_intf_real)一样冗长,因此可能不是OP 正在寻找什么...


一种稍微不同的方法可能是将f定义为接收class(*)变量的特定函数,在内部使用select type f,然后从 g 调用这个 f。如果arg只是从g(或任何其他函数)传递到f,这可能会使代码更简单。

module test_m
    implicit none

    type A_t
    contains
        procedure :: f_int
        procedure :: f_real
        procedure :: f
    endtype

    type B_t
        type(A_t) :: A
    contains
        procedure :: g
    endtype

contains

contains

    subroutine f_int( me, n )
        class(A_t) :: me
        integer :: n
        print *, "f_int  : ", n
    endsubroutine

    subroutine f_real( me, x )
        class(A_t) :: me
        real :: x
        print *, "f_real :", x
    endsubroutine

    subroutine f( me, arg )
        class(A_t) :: me
        class(*) :: arg

        select type ( arg )
          type is ( integer ) ; call me % f_int ( arg )
          type is ( real    ) ; call me % f_real( arg )
        endselect
    endsubroutine

    subroutine g( me, str, arg )
        class(B_t) :: me
        character(*) :: str
        class(*) :: arg

        print *, "g : ", str
        call me % A % f( arg )
    endsubroutine

end module

上述方法也可用于扩展类型,例如

module test_m
    implicit none

    ! same definition for A_t

    type, extends(A_t) :: B_t
    contains
        procedure :: g
    endtype

contains

    ! same definition for f_int, f_real, and f

    subroutine g( me, str, arg )
        class(B_t) :: me
        character(*) :: str
        class(*) :: arg

        print *, "g : ", str
        call me % A_t % f( arg )
    endsubroutine

end module

但我希望有其他方法可以直接将 arg 传递给泛型函数 f,而不使用 select type

关于generics - 如何直接使用泛型函数定义一个新的Fortran过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44796090/

相关文章:

java - 将 java 泛型用于简单工厂 - 如何避免这些警告

javascript - 如何创建一个扩展 React.Component 的 BaseClass,以便我的所有其他类都扩展 BaseClass 并可以指定自己的 Props 和 State 类型?

python - f2py - 函数参数的顺序困惑

vim - 在 Vim 中缩进 Fortran 代码

arrays - 在 Fortran 中的数组子集上使用 BLAS ?gemm

fortran - MPI 组未分配正确的处理器等级

fortran - 在 Fortran 中写入现有文件而不覆盖

Java 泛型在方法的返回类型之前限制通配符的使用

c# - 为什么通用类型在 CIL 中的函数定义处看起来像 (!!T)

java - Java 中的通用特征