gpt4 book ai didi

generics - 在 Fortran 90 中为抽象类型创建接口(interface)

转载 作者:行者123 更新时间:2023-12-04 12:52:20 25 4
gpt4 key购买 nike

我在 Fortran90 中编码,即使我知道应该避免它,我也需要使用抽象类型。现在我想定义一个函数,它可以在参数中采用抽象类型或派生类型。为此,我想创建两个函数的接口(interface),但出现以下错误:

Ambiguous interfaces 'initialize_abstract' and 'initialize_logic' in generic interface 'initialize' at (1)

代码如下:

type type1
contains
procedure, pass(transf) :: initialize_logic
procedure, pass(transf) :: initialize_abstract
end type

interface initialize
module procedure initialize_logic
module procedure initialize_abstract
end interface

function initialize_logic(element, element_logic)
type(type1), pointer :: element
type(type_logic), pointer :: element_logic
end function

function initialize_abstract(element, element_abstract)
type(type1), pointer :: element
class(type_abstract), pointer :: element_abstract
end function

type_abstract 是从 type_logic 扩展而来的。

我不知道如何摆脱这个消息错误,我真的需要能够用抽象类型或扩展类型(这里:“logic_type”)调用它,例如:

class(type_abstract), pointer :: element_abstract
type(type_logic), pointer :: element_logic
type(type1) :: e1, e2
call e1%initialize(element_abstract)
call e2%initialize(element_logic)

如果我只有一个初始化器,接受抽象类的参数,在使用扩展类型初始化时,我会得到以下错误:

Error: Actual argument to 'element_abstract' at (1) must have the same declared type

有什么想法吗?提前谢谢你

最佳答案

编辑:完全重做,添加了抽象类方法。

有两种方法可以做到这一点。在运行时使用select type 构造来确定element 的动态类型,以调用正确的初始化过程。

另一种方法使用抽象类来声明延迟过程initialize_t1,每个子类将以不同方式实现该过程。请注意两件事,首先,我将其中一种派生类型称为 abstract 以保持您的命名约定,但它相当困惑并且不是一个好的做法。然后将真正的抽象类称为 veryAbstract 以暗示其用途并仍然保持您的命名约定。另一点需要注意的是,initialize_from_... 过程绑定(bind)到 veryAbstract 子类,而不是 type1 类。这可能令人困惑,但这是实现您所追求的目标的技巧。

这两种方式都使用ifort 14进行了测试。

方法 1(选择类型):

module test2

type abstract
integer :: x
contains
end type abstract

type, extends(abstract) :: logic
integer :: y
contains
end type logic

type type1
integer :: x
contains
procedure :: initialize => initialize_type1
procedure :: initialize_abstract
procedure :: initialize_logic
end type type1

contains

subroutine initialize_abstract(this,element)
class(type1), intent(inout) :: this
class(abstract), intent(in) :: element
this%x = element%x
end subroutine initialize_abstract

subroutine initialize_logic(this,element)
class(type1), intent(inout) :: this
class(logic), intent(in) :: element
this%x = element%y
end subroutine initialize_logic

subroutine initialize_type1(this,element)
class(type1), intent(inout) :: this
class(abstract), intent(in) :: element

select type (element)
type is (abstract)
call this%initialize_abstract(element)
type is (logic)
call this%initialize_logic(element)
class default
print*,"ERROR: Unknown type of the 'element' argument in 'initialize_type1'."
stop
end select
end subroutine initialize_type1
end module test2

方法 2(抽象类):

module test3
type type1
integer :: x
contains
procedure :: initialize => initialize_type1
end type type1

type, abstract :: veryAbstract
contains
procedure(init_t1), deferred :: initialize_t1
end type veryAbstract

abstract interface
subroutine init_t1(this,t1)
import veryAbstract
import type1
class(veryAbstract), intent(in) :: this
class(type1), intent(inout) :: t1
end subroutine
end interface

type, extends(veryAbstract) :: abstract
integer :: x
contains
procedure :: initialize_t1 => initialize_type1_from_abstract
end type abstract

type, extends(abstract) :: logic
integer :: y
contains
procedure :: initialize_t1 => initialize_type1_from_logic
end type logic

contains

subroutine initialize_type1(this,element)
class(type1), intent(inout) :: this
class(abstract), intent(in) :: element
call element%initialize_t1(this)
end subroutine initialize_type1

subroutine initialize_type1_from_abstract(this,t1)
class(abstract), intent(in) :: this
class(type1), intent(inout) :: t1
t1%x = this%x
end subroutine initialize_type1_from_abstract

subroutine initialize_type1_from_logic(this,t1)
class(logic), intent(in) :: this
class(type1), intent(inout) :: t1
t1%x = this%y
end subroutine initialize_type1_from_logic

end module test3

测试程序:

PROGRAM test 
use test2
!use test3

type(abstract) :: a1
type(logic) :: l1
type(type1) :: t1
type(type1) :: t2

a1%x = 1
l1%x = 2
l1%y = 7
call t1%initialize(a1)
call t2%initialize(l1)

print*,'t1%x: ',t1%x
print*,'t2%x: ',t2%x
end

关于generics - 在 Fortran 90 中为抽象类型创建接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25683298/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com