在 Fortran 中选择 class 中的过程
Selecting procedures within a class in Fortran
我们如何select程序内类?编译错误为:
$ 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
(第 48 行)中 module mIntermediates
(第 28 行)。参数 sub
将是 compute_intermediates_dot
或 compute_intermediates_sum
.
MWE 代码 driver.f08
尝试 select 计算路径。调用两个选项 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
子程序 local_selector_sub
中的虚拟过程 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
本身成为 accessible/public 并传递它。但我很想坚持在其他两条线之间进行选择。
或者,如果您确实希望 select 将子例程传递给 myIntermediates%local_selector
,那么您可以考虑使用过程指针组件而不是类型绑定过程。
我们如何select程序内类?编译错误为:
$ 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
(第 48 行)中 module mIntermediates
(第 28 行)。参数 sub
将是 compute_intermediates_dot
或 compute_intermediates_sum
.
MWE 代码 driver.f08
尝试 select 计算路径。调用两个选项 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
子程序 local_selector_sub
中的虚拟过程 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
本身成为 accessible/public 并传递它。但我很想坚持在其他两条线之间进行选择。
或者,如果您确实希望 select 将子例程传递给 myIntermediates%local_selector
,那么您可以考虑使用过程指针组件而不是类型绑定过程。