繁体   English   中英

Fortran 2008 - 用户定义的CLASS I / O过程(*)

[英]Fortran 2008 - user defined I/O procedure for CLASS(*)

我正在尝试创建一个类型,它可以作为任意其他类型的包装器,因此我可以创建一个异构数组,因为它建议在Fortran类的异构数组和Fortran中 创建异构数组

所以,我试图像这样实现它:

module m
implicit none

type :: container
    class(*), pointer, public :: item
end type container
end module m

program mwe 
use m

implicit none

type(container) :: cont
integer, target :: i

i = 5 
cont = container(i)

write(*,*) cont%item

end program mwe 

现在我收到了错误

test4.f90(20): error #5513: A polymorphic I/O list item requires a user-defined derived-type input/output procedure.
    write(*,*) cont%item
----^
compilation aborted for test4.f90 (code 1)

所以我尝试像这样实现I / O:

module m
    implicit none

    type :: container
        class(*), pointer, public :: item
    contains
        procedure :: write_sample => write_container_sample_impl
        procedure :: read_sample  => read_container_sample_impl

        generic   :: write(unformatted) => write_sample
        generic   :: read(unformatted) => read_sample
    end type container

contains

    subroutine write_container_sample_impl(this, unit, iostat, iomsg)
        class(container), intent(in)    :: this
        integer, intent(in)         :: unit
        integer, intent(out)        :: iostat
        character(*), intent(inout) :: iomsg

        write(unit, iostat=iostat, iomsg=iomsg) this%item
    end subroutine write_container_sample_impl

    subroutine read_container_sample_impl(this, unit, iostat, iomsg)
        class(container), intent(inout) :: this
        integer, intent(in)         :: unit
        integer, intent(out)        :: iostat
        character(*), intent(inout) :: iomsg

        read(unit, iostat=iostat, iomsg=iomsg) this%item
    end subroutine read_container_sample_impl

end module m

program mwe 
    use m

    implicit none

    type(container) :: cont
    integer, target :: i

    i = 5 
    cont = container(i)

    write(*,*) cont%item

end program mwe 

但即使在我的新方法中也会出现同样的错误:

test4.f90(22): error #5513: A polymorphic I/O list item requires a user-defined derived-type input/output procedure.
        write(unit, iostat=iostat, iomsg=iomsg) this%item
--------^
test4.f90(31): error #5513: A polymorphic I/O list item requires a user-defined derived-type input/output procedure.
        read(unit, iostat=iostat, iomsg=iomsg) this%item
--------^
test4.f90(47): error #5513: A polymorphic I/O list item requires a user-defined derived-type input/output procedure.
    write(*,*) cont%item
----^

所以,我有两个问题

  1. 我该如何正确实施?
  2. 变量声明为指针或可分配变量是更好/更容易吗?

使用无限多态实体是非常苛刻的。

为容器类型添加已定义的输入/输出过程并不能解决您的问题,因为问题不在于容器本身。 相反,它是容器的组件 ,它是多态的并且需要定义的I / O过程。

不幸的是,因为该组件是无限多态的,所以不可能定义这样的过程。 1

此外,实际上不会使用您定义的容器类型的I / O过程。 您只为未格式化的输入和输出定义了过程,但write(*,*)是(列表定向的)格式化输出。

至于如何解决这个问题:在某些时候你必须决定你的无限多态实体是什么。 使用无限多态实体的部分原因是棘手的,因为内部和派生类型不能被视为相同。 与上一个问题一样,如果您可以使用class(something_not_star)而不是class(*)您会发现生活更轻松。

有了它们的方式, select type可能是你最好的希望。


1定义的I / O过程可能仅适用于派生类型。

我实现类似的东西的方式是这样的

module container_mod

implicit none
private
!Public access vars
public :: container

type container !< Unlimited polymorphic container class 
    private !contents are only accessible trough the methods, no direct access is allowed
    class(*), pointer :: value => null() !< value stored in container
contains
procedure :: getContent     !< returns stored content (pointer)
procedure :: storeContent   !< stores the provided values (sourced allocation)
procedure :: printContainer !< prints container contents (only primitive types implemented)
end type container

interface container
    procedure constructor !< construct/initialize a container
end interface

程序定义如下

function getContent(this)
class(container), intent(in) :: this
class(*), pointer :: getContent
getContent => this%value
end function getContent

subroutine storeContent(this,to_store)
class(container), intent(inout) :: this
class(*), intent(in) :: to_store
allocate(this%value, source=to_store)
end subroutine storeContent

subroutine printContainer(this)
class(container), intent(in) :: this
select type(v => this%value)
type is (integer)
    print *, v
type is (character(*))
    print *, v(1:1)
type is (real)
    print *, v
    class default
    print*, "[printContainer]: don't know how to print this value, ignoring"
end select
end subroutine printContainer

function constructor(to_store)
class(container), pointer :: constructor
class(*), intent(in) :: to_store
allocate(constructor)
allocate(constructor%value, source=to_store)
end function constructor

查看此存储库,因为它实现了一个容器类,并在抽象的异构数组中使用它。

一旦你检索到阵列的内容很难,就不用担心我会害怕的挡板,那就是Fortran。 如果你找到了办法, 告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM