我们如何在课程中选择程序?编译错误是:
$ 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_dot
或compute_intermediates_sum
。
MWE代码driver.f08
尝试选择计算路径。调用两个选项compute_intermediates_sum
和compute_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
答案 0 :(得分:3)
子例程sub
中的虚拟过程local_selector_sub
具有接口块给出的接口。那个界面
interface
subroutine sub
end subroutine sub
end interface
(冗余use
和import
以及未使用的通用名称已删除)表示sub
没有参数。在下面的调用中,您尝试给它两个参数,编译器正确地抱怨它。
要解决此问题,您需要正确指定接口(或依赖于隐式接口)。我注意到,compute_intermediates_dot_sub
和compute_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
的子例程,那么您可以考虑使用过程指针组件而不是类型绑定过程。