Fortran 2008 - 用户为 CLASS(*) 定义的 I/O 过程
Fortran 2008 - user defined I/O procedure for CLASS(*)
我正在尝试创建一个类型,它可以作为任意其他类型的包装器,因此我可以创建一个异构数组,正如 and 中所建议的那样。
所以,我试过这样实现它:
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
----^
所以,我有两个问题:
- 我该如何正确实施?
- 是better/easier将item变量声明为指针还是可分配变量?
处理无限多态实体要求很高。
为容器类型添加已定义的 input/output 过程并不能解决您的问题,因为问题不在于容器本身。相反,容器的 component 是多态的,需要定义的 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
查看 this repository,因为它实现了容器 class 并将其用于抽象异构数组。
一旦你检索了数组的内容,恐怕就没有办法绕过类型保护了,这就是适合你的 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
----^
所以,我有两个问题:
- 我该如何正确实施?
- 是better/easier将item变量声明为指针还是可分配变量?
处理无限多态实体要求很高。
为容器类型添加已定义的 input/output 过程并不能解决您的问题,因为问题不在于容器本身。相反,容器的 component 是多态的,需要定义的 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
查看 this repository,因为它实现了容器 class 并将其用于抽象异构数组。
一旦你检索了数组的内容,恐怕就没有办法绕过类型保护了,这就是适合你的 Fortran。如果您确实找到了方法,请 告诉我。