在Fortran中选择类中的过程

时间:2015-12-14 21:38:47

标签: class fortran gfortran subroutine

我们如何在课程中选择程序?编译错误是:

$ gfortran  -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fbacktrace -g  -fmax-errors=5 driver.f08 
driver.f08:60:39:

         call sub ( me, myMeasurements )
                                       1
Error: More actual than formal arguments in procedure call at (1)

发生在subroutine local_selector_sub内的module mIntermediates(第48行)。参数sub可以是compute_intermediates_dotcompute_intermediates_sum

MWE代码driver.f08尝试选择计算路径。调用两个选项compute_intermediates_sumcompute_intermediates_dot都可以正常工作(第93,94行)。

问题是调用local_selector(第95行),其中包含目标计算路径的名称。目标是有不同的表现形式,如

call myIntermediates % local_selector( compute_intermediates_sum, myMeasurements )

call myIntermediates % local_selector( compute_intermediates_dot, myMeasurements )

MWE:

module mMeasurements  !   *   *   *

    implicit none
    integer, parameter :: m = 2

    type :: measurements
        real, dimension ( 1 : m ) :: x = 0.0, y = 0.0, ones = 1.0, residuals = 0.0
    contains
        private
        procedure, public :: load_data
    end type measurements

contains

    subroutine load_data ( me )

        class ( measurements ), target :: me

            me % x ( 1 ) = 1.0 !           load data
            me % x ( 2 ) = 2.0
            me % y ( 1 ) = 15.6
            me % y ( 2 ) = 17.5

    end subroutine load_data

end module mMeasurements

module mIntermediatesDefinitions  !   *   *   *

    use mMeasurements
    implicit none

    type :: intermediates
        real :: sxy = 0.0
    contains
        private
        procedure, public :: compute_intermediates_dot => compute_intermediates_dot_sub
        procedure, public :: compute_intermediates_sum => compute_intermediates_sum_sub
        procedure, public :: local_selector            => local_selector_sub
    end type intermediates

    private :: local_selector_sub
    private :: compute_intermediates_dot_sub
    private :: compute_intermediates_sum_sub

contains

    subroutine local_selector_sub ( me, sub, myMeasurements )  ! problematic routine

        class ( intermediates ), target      :: me
        type ( measurements ), intent ( in ) :: myMeasurements

        interface mySub
            subroutine sub
                use mMeasurements
                import intermediates
            end subroutine sub
        end interface mySub

        call sub ( me, myMeasurements )

    end subroutine local_selector_sub

    subroutine compute_intermediates_dot_sub ( me, myMeasurements )

        class ( intermediates ), target      :: me
        type ( measurements ), intent ( in ) :: myMeasurements

            me % sxy = dot_product ( myMeasurements % x,    myMeasurements % y )

    end subroutine compute_intermediates_dot_sub

    subroutine compute_intermediates_sum_sub ( me, myMeasurements )

        class ( intermediates ), target      :: me
        type ( measurements ), intent ( in ) :: myMeasurements

            me % sxy = sum ( myMeasurements % x * myMeasurements % y )

    end subroutine compute_intermediates_sum_sub

end module mIntermediatesDefinitions

program driver  !   #   #   #

    use mMeasurements
    use mIntermediatesDefinitions

    implicit none
    type ( measurements )  :: myMeasurements
    type ( intermediates ) :: myIntermediates

        call myIntermediates % compute_intermediates_dot ( myMeasurements )
        call myIntermediates % compute_intermediates_sum ( myMeasurements )
        call myIntermediates % local_selector            ( compute_intermediates_dot, myMeasurements )

end program driver

版本:     GNU Fortran (GCC) 5.1.0

1 个答案:

答案 0 :(得分:3)

子例程sub中的虚拟过程local_selector_sub具有接口块给出的接口。那个界面

interface
  subroutine sub
  end subroutine sub
end interface

(冗余useimport以及未使用的通用名称已删除)表示sub没有参数。在下面的调用中,您尝试给它两个参数,编译器正确地抱怨它。

要解决此问题,您需要正确指定接口(或依赖于隐式接口)。我注意到,compute_intermediates_dot_subcompute_intermediates_sum_sub选项具有您可以编写的相同特征,例如

subroutine local_selector_sub ( me, sub, myMeasurements )  ! problematic routine
  class ( intermediates ), target          :: me
  type ( measurements ), intent ( in )     :: myMeasurements
  procedure(compute_intermediates_dot_sub)    sub

  call sub ( me, myMeasurements )

end subroutine

(或者您可以创建一个中性命名的抽象接口或使用适当的接口块)。

但这导致了一个更有趣的问题:

call myIntermediates%local_selector(compute_intermediates_dot, myMeasurements)

compute_intermediates_dot不是子程序。它是类型intermediates的类型绑定过程的绑定名称。

如果您希望将子例程传递给myIntermediates%local_selector,最简单的解决方案是使子例程compute_intermediates_dot_sub本身可访问/公共并传递它。但我很想坚持选择其他两行。

或者,如果您真的希望选择要传递给myIntermediates%local_selector的子例程,那么您可以考虑使用过程指针组件而不是类型绑定过程。