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

时间:2017-06-28 07:24:53

标签: 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,...的不同类型定义很多子例程input。但这是愚蠢的,因为f已经考虑过这类事情。如何避免这种烦恼?

1 个答案:

答案 0 :(得分:0)

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

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&amp; 7.1:

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

但上面的代码与在f_int内调用特定函数(f_realselect type)一样冗长,因此它可能不是OP正在寻找的......

稍微不同的方法可能是将f定义为接收class(*)变量的特定函数,在select type中使用f,然后调用此{{1}来自f。如果g只是从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还有其他方法。