Ошибка: если выражение селектора в SELECT TYPE не является именованной переменной, должно появиться ассоциированное имя=>

Я пытаюсь использовать тип в другом типе. Однако я просто не могу его скомпилировать. Мне это странно: в основной программе работает выбор типа, а в подпрограмме тип не работает.

module ModBuffer
    implicit none
    private
    type, abstract, public :: Buffer
    contains
        procedure, public                       :: Constructor
    endtype Buffer

    type, extends(Buffer), public :: BufferR
        real(8), allocatable, public            :: BufData(:,:,:)
    endtype BufferR

    type, extends(Buffer), public :: BufferI
        complex(8), allocatable, public         :: BufData(:,:,:)
    endtype BufferI

    contains

    subroutine Constructor(this, dim1, dim2, dim3)
        class(Buffer), intent(inout)            :: this
        integer, intent(in)                     :: dim1, dim2, dim3

        select type(this)
        type is(BufferR)
            allocate(this%BufData(dim1, dim2, dim3))
        type is(BufferI)
            allocate(this%BufData(dim1, dim2, dim3))
        endselect
    endsubroutine Constructor
endmodule ModBuffer

module ModSystem
    use ModBuffer
    implicit none
    private
    type, public :: System
        class(Buffer), allocatable, public :: WF
    contains
    endtype System

    type, extends(System) :: NewSystem
    contains
        procedure, public :: Constructor
    endtype NewSystem

    contains

    subroutine Constructor(this, Flag)
        class(NewSystem), intent(inout) :: this
        logical, intent(in) :: Flag

        if(Flag) then
            allocate(BufferR::this%WF)
        else
            allocate(BufferI::this%WF)
        endif
        select type(this%WF)
        type is(BufferR)
            print *, "Buffer is real."
        type is(BufferI)
            print *, "Buffer is complex."
        endselect
    endsubroutine Constructor
endmodule ModSystem


program test
    use ModSystem
    !use Operation
    class(System), allocatable :: s

    allocate(NewSystem::s)
    call s%Constructor(.true.)
endprogram test

Я получил ошибку компиляции в строке select type(this%WF). Но если я определю тип Buffer в основной программе и сделаю то же самое, ошибки не будет.

Сообщение об ошибке:

error #8253: If selector expression in SELECT TYPE is not a named variable, associate-name=> shall appear.

Как я могу компилировать этот код?


person FortCpp    schedule 26.09.2014    source источник
comment
Лично я бы не проголосовал за это, но у некоторых людей аллергия на то, что это не работает, и я получил сообщение об ошибке, не указав, как это не работает и как выглядит ошибка. Никто, вероятно, не проголосует за real(8), хотя это не очень разумная практика.   -  person Vladimir F    schedule 27.09.2014
comment
Соглашаясь с Владимиром Ф, еще добавлю: кода много, неужели это самая простая/общая кучка, в которой есть проблема? Вы говорите, что это работает с модификацией: что это за модификация? Точное сообщение об ошибке также полезно: мы хотим, чтобы люди с такой же проблемой в других проектах могли найти ответ. Это также полезная подсказка для тех, кто знает ответ.   -  person francescalus    schedule 27.09.2014
comment
@VladimirF Не могли бы вы объяснить немного больше о том, что никто, вероятно, не проголосует за настоящий (8). Я думаю, что real(8) - это замена двойной точности. И я знаю, что гораздо лучше использовать переменную для указания вида. Пожалуйста, расскажите мне немного больше о вашем мнении. Спасибо.   -  person FortCpp    schedule 27.09.2014
comment
См. stackoverflow.com/questions/838310/fortran-90 -kind-parameter/ и stackoverflow.com/questions/22362211/ kind=8 может означать что-то другое на разных платформах. Портативные решения используют select_real_kind, iso_fortran_env или iso_c_binding.   -  person Vladimir F    schedule 27.09.2014


Ответы (2)


Нет причин использовать указатель, просто используйте ассоциативную часть select type (вы не написали сообщение об ошибке, но IIRC вполне описателен):

   select type (twf => this%WF)
person Vladimir F    schedule 27.09.2014
comment
Здорово! Работает как шарм. - person FortCpp; 27.09.2014

Я понятия не имею, почему эта тема проголосовала. Но я нахожу решение. Кстати, я использую IVF на Windows (которую я не обновлял несколько месяцев).

Кажется, я не могу использовать член типа в предложении «выбрать тип» для запуска ошибки компилятора IVF. Но если вы установите указатель на элемент, все будет работать нормально. Это немного запрограммированный указатель, решающий проблему, и в этом нет особого смысла.

module ModBuffer
    implicit none
    private
    type, abstract, public :: Buffer
    contains
        procedure, public                       :: Constructor
    endtype Buffer

    type, extends(Buffer), public :: BufferR
        real(8), allocatable, public            :: BufData(:,:,:)
    endtype BufferR

    type, extends(Buffer), public :: BufferI
        complex(8), allocatable, public         :: BufData(:,:,:)
    endtype BufferI

    contains

    subroutine Constructor(this, dim1, dim2, dim3)
        class(Buffer), intent(inout)            :: this
        integer, intent(in)                     :: dim1, dim2, dim3

        select type(this)
        type is(BufferR)
            allocate(this%BufData(dim1, dim2, dim3))
        type is(BufferI)
            allocate(this%BufData(dim1, dim2, dim3))
        endselect
    endsubroutine Constructor
endmodule ModBuffer

module ModSystem
    use ModBuffer
    implicit none
    private
    type, public :: System
        class(Buffer), allocatable, public :: WF
    contains
    endtype System

    type, extends(System), public :: NewSystem
    contains
        procedure, public :: Constructor
    endtype NewSystem

    contains

    subroutine Constructor(this, Flag)
        class(NewSystem), intent(inout) :: this
        logical, intent(in) :: Flag
        class(Buffer), pointer :: P

        if(Flag) then
            allocate(BufferR::this%WF)
        else
            allocate(BufferI::this%WF)
        endif
        call SetPointer(P, this%WF)
        select type(P)
        type is(BufferR)
            print *, "Buffer is real."
        type is(BufferI)
            print *, "Buffer is complex."
        endselect
    endsubroutine Constructor

    subroutine SetPointer(MyP, MyA)
        class(Buffer), pointer :: MyP
        class(Buffer), target :: MyA
        MyP => MyA
    endsubroutine SetPointer
endmodule ModSystem


program test
    use ModSystem
    !use Operation
    class(System), allocatable :: s

    allocate(NewSystem::s)
    select type(s)
    type is(NewSystem)
        call s%Constructor(.true.)
    endselect
endprogram test
person FortCpp    schedule 27.09.2014