[英]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 : 所以,我有两个问题 :
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.