我可以根据参数的数量重载类型绑定过程吗?
Can I overload a type-bound procedure based on the number of arguments?
我正在使用良好的旧 Fortran 编写空气动力学代码(源代码 here)。初始化的一部分是读取包含表面网格信息的文件,基本上是一组构成表面的三角形或四边形面板。我想用一种类型 panel
来描述四边形和三角形面板。为此,我编写了两个初始化函数 panel_init_3
和 panel_init_4
,它们将根据面板的顶点数量将数据加载到类型中。我想将它们绑定到我的 panel
类型并根据参数的数量重载它们(即如果它传递一个整数和 3 个顶点对象,那么 panel_init_3
被调用并且类似地用于 4 个顶点对象。
这是类型的源代码:
module panel_mod
use linked_list_mod
use vertex_mod
implicit none
type panel
! A panel with an arbitrary number of sides
integer :: N ! Number of sides/vertices
type(vertex_pointer),dimension(:),allocatable :: vertices
real,dimension(3) :: n_hat ! Normal vector
real :: A ! Surface area
contains
procedure :: init => panel_init_3, panel_init_4
procedure :: calc_area => panel_calc_area
procedure :: calc_normal => panel_calc_area
end type panel
contains
subroutine panel_init_3(this, v1, v2, v3)
! Initializes a 3-panel
implicit none
class(panel),intent(inout) :: this
type(vertex),intent(in),target :: v1, v2, v3
! Set number of sides
this%N = 3
! Allocate vertex array
allocate(this%vertices(this%N))
! Store info
this%vertices(1)%ptr => v1
this%vertices(2)%ptr => v2
this%vertices(3)%ptr => v3
! Calculate normal vec
! Calculate area
end subroutine panel_init_3
subroutine panel_init_4(this, v1, v2, v3, v4)
! Initializes a panel with 4 sides
implicit none
class(panel),intent(inout) :: this
type(vertex),intent(in),target :: v1, v2, v3, v4
! Set number of sides
this%N = 4
! Allocate vertex array
allocate(this%vertices(this%N))
! Store info
this%vertices(1)%ptr => v1
this%vertices(2)%ptr => v2
this%vertices(3)%ptr => v3
this%vertices(4)%ptr => v4
! Calculate normal vector
! Calculate area
end subroutine panel_init_4
subroutine panel_calc_area(this)
implicit none
class(panel),intent(inout) :: this
end subroutine panel_calc_area
subroutine panel_calc_normal(this)
implicit none
class(panel),intent(inout) :: this
end subroutine panel_calc_normal
end module panel_mod
此模块编译正常。但是,当它在这里被使用时
...
! Initialize triangular panel
if (N == 3) then
call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1)) ! Need +1 because VTK is 0-indexed
! Initialize quadrilateral panel
else
call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1), vertices(i4+1))
end if
...
我收到编译器消息
70 | call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1), vertices(i4+1))
| 1
Error: More actual than formal arguments in procedure call at (1)
我是否超出了 Fortran 的能力范围,或者是否有办法做到这一点?我意识到我可以在没有绑定和超载的情况下完成这一切,但我喜欢它的干净程度。我正在使用 gfortran 9.3.0.
可以,但是您需要将 init
定义为通用过程(绑定),另外两个是特定过程(绑定)
contains
procedure :: panel_init_3
procedure :: panel_init_4
generic :: init => panel_init_3, panel_init_4
这与通常使用命名 interface
块的正常程序所做的非常相似
interface generic_init
procedure specific_init_3
procedure specific_init_4
end interface
在类型绑定过程声明语句中,可以在列表中声明多个绑定名称,因此我们可以
type mytype
contains
procedure :: binding1, binding2
end type
给出两个绑定名称。这些是单独的绑定。这些绑定名称解析为与每个名称相同的过程。也就是说,我们可以把这个写成
type mytype
contains
procedure :: binding1 => binding1, binding2 => binding2
end type
绑定名称的列表性质是这样的
type mytype
contains
procedure :: binding => binding1, binding2
end type
具有列表 binding=>binding1
和 binding2
中的项目。这个有效果
喜欢
type mytype
contains
procedure :: binding => binding1, binding2 => binding2
end type
也就是说,我们仍然有两个不同的绑定名称,每个绑定到一个过程。
我们没有具有特定过程 binding1
和 binding2
的通用 binding
绑定名称。为此,我们需要一个显式创建的泛型:
type mytype
contains
procedure :: binding1, binding2
generic :: binding => binding1, binding2
end type
在此通用语句中,列表具有 binding1
和 binding2
作为通用 binding
的具体项。这些 lists/statements 的精确语法规则在 Fortran 2018 7.5.5.
中给出
我正在使用良好的旧 Fortran 编写空气动力学代码(源代码 here)。初始化的一部分是读取包含表面网格信息的文件,基本上是一组构成表面的三角形或四边形面板。我想用一种类型 panel
来描述四边形和三角形面板。为此,我编写了两个初始化函数 panel_init_3
和 panel_init_4
,它们将根据面板的顶点数量将数据加载到类型中。我想将它们绑定到我的 panel
类型并根据参数的数量重载它们(即如果它传递一个整数和 3 个顶点对象,那么 panel_init_3
被调用并且类似地用于 4 个顶点对象。
这是类型的源代码:
module panel_mod
use linked_list_mod
use vertex_mod
implicit none
type panel
! A panel with an arbitrary number of sides
integer :: N ! Number of sides/vertices
type(vertex_pointer),dimension(:),allocatable :: vertices
real,dimension(3) :: n_hat ! Normal vector
real :: A ! Surface area
contains
procedure :: init => panel_init_3, panel_init_4
procedure :: calc_area => panel_calc_area
procedure :: calc_normal => panel_calc_area
end type panel
contains
subroutine panel_init_3(this, v1, v2, v3)
! Initializes a 3-panel
implicit none
class(panel),intent(inout) :: this
type(vertex),intent(in),target :: v1, v2, v3
! Set number of sides
this%N = 3
! Allocate vertex array
allocate(this%vertices(this%N))
! Store info
this%vertices(1)%ptr => v1
this%vertices(2)%ptr => v2
this%vertices(3)%ptr => v3
! Calculate normal vec
! Calculate area
end subroutine panel_init_3
subroutine panel_init_4(this, v1, v2, v3, v4)
! Initializes a panel with 4 sides
implicit none
class(panel),intent(inout) :: this
type(vertex),intent(in),target :: v1, v2, v3, v4
! Set number of sides
this%N = 4
! Allocate vertex array
allocate(this%vertices(this%N))
! Store info
this%vertices(1)%ptr => v1
this%vertices(2)%ptr => v2
this%vertices(3)%ptr => v3
this%vertices(4)%ptr => v4
! Calculate normal vector
! Calculate area
end subroutine panel_init_4
subroutine panel_calc_area(this)
implicit none
class(panel),intent(inout) :: this
end subroutine panel_calc_area
subroutine panel_calc_normal(this)
implicit none
class(panel),intent(inout) :: this
end subroutine panel_calc_normal
end module panel_mod
此模块编译正常。但是,当它在这里被使用时
...
! Initialize triangular panel
if (N == 3) then
call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1)) ! Need +1 because VTK is 0-indexed
! Initialize quadrilateral panel
else
call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1), vertices(i4+1))
end if
...
我收到编译器消息
70 | call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1), vertices(i4+1))
| 1
Error: More actual than formal arguments in procedure call at (1)
我是否超出了 Fortran 的能力范围,或者是否有办法做到这一点?我意识到我可以在没有绑定和超载的情况下完成这一切,但我喜欢它的干净程度。我正在使用 gfortran 9.3.0.
可以,但是您需要将 init
定义为通用过程(绑定),另外两个是特定过程(绑定)
contains
procedure :: panel_init_3
procedure :: panel_init_4
generic :: init => panel_init_3, panel_init_4
这与通常使用命名 interface
块的正常程序所做的非常相似
interface generic_init
procedure specific_init_3
procedure specific_init_4
end interface
在类型绑定过程声明语句中,可以在列表中声明多个绑定名称,因此我们可以
type mytype
contains
procedure :: binding1, binding2
end type
给出两个绑定名称。这些是单独的绑定。这些绑定名称解析为与每个名称相同的过程。也就是说,我们可以把这个写成
type mytype
contains
procedure :: binding1 => binding1, binding2 => binding2
end type
绑定名称的列表性质是这样的
type mytype
contains
procedure :: binding => binding1, binding2
end type
具有列表 binding=>binding1
和 binding2
中的项目。这个有效果
喜欢
type mytype
contains
procedure :: binding => binding1, binding2 => binding2
end type
也就是说,我们仍然有两个不同的绑定名称,每个绑定到一个过程。
我们没有具有特定过程 binding1
和 binding2
的通用 binding
绑定名称。为此,我们需要一个显式创建的泛型:
type mytype
contains
procedure :: binding1, binding2
generic :: binding => binding1, binding2
end type
在此通用语句中,列表具有 binding1
和 binding2
作为通用 binding
的具体项。这些 lists/statements 的精确语法规则在 Fortran 2018 7.5.5.