2015-12-14 56 views
2

我們如何在類中選擇程序?編譯錯誤是:在Fortran中的類中選擇程序

$ 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_submodule mIntermediates(第28行)(行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

回答

3

在子程序local_selector_sub僞程序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本身可以訪問/ public並傳遞它。不過,我會忍不住要堅持與其他兩條線之間進行選擇。

或者,如果你真的想選擇一個子程序傳遞到myIntermediates%local_selector,那麼你可以考慮讓程序指針組成部分,而不是類型綁定程序。