在 Fortran 中从外部 类 传递子例程名称

Passing subroutine names from external classes in Fortran

中,我们学习了如何在 Fortran classes 中将子例程名称作为参数传递。但是我们如何从外部传递子程序名称 class?

随后的代码为使用 GNU Fortran (GCC) 5.1.0 的两次不同尝试产生编译错误:

gfortran  -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5 casey.f08 
casey.f08:42:37:

         call selector ( ints % square, x , y )
                                     1
Error: Expected argument list at (1)
casey.f08:43:24:

         call selector ( ints % double ( x, y ), x , y )
                        1
Error: ‘double’ at (1) should be a FUNCTION

例程 selector 的目标是采用不同的计算路径:一个计算一个数的平方,另一个计算它的两倍。第一个编译错误建议添加一个参数列表。对此的幼稚补救措施会产生第二个错误。

随后是 MWE。排列编程产生了许多变体;希望这个版本可以轻松修复。

module myModule

    implicit none

    type     :: intermediates
        real :: z
    contains
        private
        procedure, nopass, public :: square => square_sub
        procedure, nopass, public :: double => double_sub
    end type intermediates

    private :: square_sub
    private :: double_sub

contains

    subroutine square_sub ( x, y )
        real, intent ( in )  :: x
        real, intent ( out ) :: y
            y = x ** 2
    end subroutine square_sub

    subroutine double_sub ( x, y )
        real, intent ( in )  :: x
        real, intent ( out ) :: y
            y = x * 2
    end subroutine double_sub

end module myModule


program casey

    use myModule
    implicit none

    real :: x = 10.0, y
    type ( intermediates ) :: ints
        call selector ( ints % square, x , y )
        call selector ( ints % double ( x, y ), x , y )

contains

    subroutine selector ( sub, x, y )

        interface mySub
            subroutine sub ( x, y )
                real, intent ( in )  :: x
                real, intent ( out ) :: y
            end subroutine sub
        end interface mySub

        real, intent ( in )  :: x
        real, intent ( out ) :: y

            call sub ( x, y )
            print *, 'x = ', x, ', y = ', y

    end subroutine selector

end program casey

解决方案是将选择器过程放在 class 中。在上面的示例中,subroutine selectorprogram 内。 subroutine local_selector 下面是 mySubs.

类型的 procedure
module mySubs

    implicit none

    type :: myClass
    contains
        procedure, nopass, public :: square
        procedure, nopass, public :: double
        procedure, nopass, public :: local_selector
    end type myClass

contains

    subroutine square ( x, y )
        real, intent ( in )  :: x
        real, intent ( out ) :: y
            y = x ** 2
            print *, 'x = ', x, '; x ** 2 = ', y
    end subroutine square

    subroutine double ( x, y )
        real, intent ( in )  :: x
        real, intent ( out ) :: y
            y = x * 2
            print *, 'x = ', x, '; 2 x = ', y
    end subroutine double

    subroutine local_selector ( sub, x, y )

        interface mySub
            subroutine sub ( x, y )
                real, intent ( in )  :: x
                real, intent ( out ) :: y
            end subroutine sub
        end interface mySub

        real, intent ( in )  :: x
        real, intent ( out ) :: y

            call sub ( x, y )

    end subroutine local_selector

end module mySubs

program fixed

    use mySubs
    implicit none

    real :: x = 10.0, y

    type ( myClass ) :: thisClass

        call thisClass % local_selector ( square, x , y )
        call thisClass % local_selector ( double, x , y )

end program fixed