Fortran 2008 - пользовательская процедура ввода / вывода для CLASS (*) - PullRequest
0 голосов
/ 06 июня 2018

Я пытаюсь создать тип, который будет служить оберткой для произвольных других типов, чтобы я мог создать гетерогенный массив, как рекомендуется в Гетерогенный массив классов Фортрана и Создание гетерогенных массивов в 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)

Поэтому я попытался реализовать ввод / вывод следующим образом:

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. Лучше / проще объявить переменную item в качестве указателя или каквыделяемая переменная?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

То, как я реализовал нечто подобное, было следующим:

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 для вас.Если вы найдете способ, , пожалуйста, , дайте мне знать.

0 голосов
/ 06 июня 2018

Требуется работа с неограниченным количеством полиморфных объектов.

Добавление определенных процедур ввода / вывода для типа контейнера не решает вашу проблему, поскольку проблема не в самом контейнере.Вместо этого это компонент контейнера, который является полиморфным и требует определенной процедуры ввода / вывода.

К сожалению, хотя, поскольку этот компонент является неограниченным полиморфным, невозможно определить такойпроцедура. 1

Кроме того, определенные вами процедуры ввода / вывода для типа контейнера фактически не будут использоваться.Вы определили процедуры только для неформатированного ввода и вывода, но write(*,*) - это форматированный вывод.

Относительно того, как вы можете решить эту проблему: в какой-то момент вы должны решить, какой у вас неограниченный полиморфизмсущность есть.Одна из причин, по которой работа с неограниченными полиморфными объектами является хитрой, заключается в том, что внутренние и производные типы не могут обрабатываться одинаково.Как и в предыдущем вопросе, если вы можете использовать class(something_not_star) вместо class(*), вы найдете жизнь проще.

С такими вещами, как они есть, select type, вероятно, ваша лучшая надежда.


1 Определенные процедуры ввода / вывода могут существовать только для производных типов.

...