简体   繁体   English

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

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

I'm trying to make a type, which would serve as a wrapper for an arbitrary other types, so I could make a heterogeneous array, as it's advised in Heterogeneous array of Fortran classes and Creating heterogeneous arrays in Fortran . 我正在尝试创建一个类型,它可以作为任意其他类型的包装器,因此我可以创建一个异构数组,因为它建议在Fortran类的异构数组和Fortran中 创建异构数组

So, I've tried to implement it like this: 所以,我试图像这样实现它:

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 

Now I'm getting error 现在我收到了错误

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)

So I tried to implement I/O like this: 所以我尝试像这样实现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 

But the same error occurs even in my new methods: 但即使在我的新方法中也会出现同样的错误:

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
----^

So, I have two questions : 所以,我有两个问题

  1. How should I implement it correctly? 我该如何正确实施?
  2. Is it better/easier to declare item variable as a pointer or as an allocatable variable? 变量声明为指针或可分配变量是更好/更容易吗?

Working with unlimited polymorphic entities is demanding. 使用无限多态实体是非常苛刻的。

Adding the defined input/output procedures for the container type doesn't solve your problem because the problem isn't with the container itself. 为容器类型添加已定义的输入/输出过程并不能解决您的问题,因为问题不在于容器本身。 Instead it is the component of the container which is polymorphic and requiring the defined I/O procedure. 相反,它是容器的组件 ,它是多态的并且需要定义的I / O过程。

Unfortunately though, because that component is unlimited polymorphic it isn't possible to define such a procedure. 不幸的是,因为该组件是无限多态的,所以不可能定义这样的过程。 1 1

Further, your defined I/O procedures for the container type won't actually be used. 此外,实际上不会使用您定义的容器类型的I / O过程。 You have defined procedures only for unformatted input and output, but write(*,*) is (list-directed) formatted output. 您只为未格式化的输入和输出定义了过程,但write(*,*)是(列表定向的)格式化输出。

As to how you can solve this problem: at some point you have to decide what your unlimited polymorphic entity is. 至于如何解决这个问题:在某些时候你必须决定你的无限多态实体是什么。 Part of the reason working with unlimited polymorphic entities is tricky is because intrinsic and derived types cannot be treated the same. 使用无限多态实体的部分原因是棘手的,因为内部和派生类型不能被视为相同。 As with your previous question, if you can use class(something_not_star) instead of class(*) you will find life easier. 与上一个问题一样,如果您可以使用class(something_not_star)而不是class(*)您会发现生活更轻松。

With things how they are, select type is probably your best hope. 有了它们的方式, select type可能是你最好的希望。


1 Defined I/O procedures may exist only for derived types. 1定义的I / O过程可能仅适用于派生类型。

The way I implemented something similar was like this 我实现类似的东西的方式是这样的

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

The procedures were defined like this 程序定义如下

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

Check out this repository as it implements a container class and uses it in an abstract heterogeneous array. 查看此存储库,因为它实现了一个容器类,并在抽象的异构数组中使用它。

Once you retrieve the contents of the array tough, there is no way around typeguards I'm afraid, that is Fortran for you. 一旦你检索到阵列的内容很难,就不用担心我会害怕的挡板,那就是Fortran。 If you do find a way, please let me know. 如果你找到了办法, 告诉我。

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

相关问题 使用定义的输入过程从Fortran中的二进制文件读取错误值 - Reading bad values from binary file in Fortran with a defined input procedure 扩展用户定义的类 - Extending a user defined class 在用户定义的类中调用用户定义的函数 - Calling User Defined Function In User Defined Class 如何在PowerShell中的用户定义类中使用用户定义的结构? - How Do I Use a User-Defined Struct in a User-Defined Class in PowerShell? Python3:如何控制用户定义类的行为? - Python3: How can I control behavior of user defined class? NameError:未定义名称“用户”; 我认为与课程有关 - NameError: name 'user' is not defined; class related I think 如果 class 实例不是调用过程中定义的变量,为什么在 class 中创建表单时出现访问冲突 - Why do I get an access violation when I create a form within a class if the class instance is not a variable defined in the calling procedure 在MATLAB中保存用户定义的类 - Saving User Defined Class in MATLAB 用户定义的类构造函数和函数无法正常工作,我是否构造了错误的类? - User defined class contructor and functions arent working, did i construct my class incorrectly? 如何将用户定义的类用作模板类的类型并正确地重载&lt;&lt;用于两个类? - How do I use a user defined class as a type of template class and properly overload the << for the two classes?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM