Передача выделяемого символа подпрограмме с неограниченным полиморфным фиктивным аргументом в Фортране

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

Отрывок из этой рутины здесь:

subroutine GetAsScalar (this, value, status)
    !Arguments-------------------------------------------------------------
    class(TKeyword)                                 ::  this
    class(*)                                        ::  value
    logical, optional                               ::  status

    !Local-----------------------------------------------------------------
    integer                                         ::  stat        

    !----------------------------------------------------------------------  

    stat = 0

    select type (value)
    type is (REAL(real32))      !single precision
        read (this%fValue, *, IOSTAT = stat) value           
    type is (REAL(real64))      !double precision
        read (this%fValue, *, IOSTAT = stat) value
    type is (LOGICAL)
        read (this%fValue, *, IOSTAT = stat) value
    type is (INTEGER(int32))    !integer
        read (this%fValue, *, IOSTAT = stat) value
    type is (INTEGER(int64))    !long integer
        read (this%fValue, *, IOSTAT = stat) value
    type is (CHARACTER(*))
        value = this%fValue
    class default            
        this%Message = "Invalid data type"
        status = .false.
        return
    end select

    if (present (status)) then
        if (stat /= 0) then
            status = .false.
        else                    
            status = .true.
        endif
    endif

end subroutine GetAsScalar

"this%fValue" представляет собой "символьную (len=:), выделяемую" строку. Когда я пытаюсь использовать эту процедуру, передавая выделяемую строку, она завершается успешно, никаких ошибок/исключений не возникает:

character(len=:), allocatable :: value
call keyword%GetAsScalar(value)

Но строка «значение» всегда пуста. Даже внутри подпрограммы после присваивания «value = this%fValue» значение пусто (len(value) равно 0).

Похоже, что компилятор не может определить, что аргумент имеет тип character(len=:), может быть размещен, и поэтому не может присвоить ему значение.

Конечно, у меня есть несколько альтернатив, но идея использовать одну процедуру и без необязательных аргументов для разных типов данных действительно хороша.

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

Но я хотел бы знать, является ли это поведением по умолчанию в Fortran 2008. А также, есть ли способ выполнить это, используя эту процедуру с одним фиктивным аргументом «класс (*)», для преобразования различных типов, включая упомянутый выделяемый символ. Например, есть способ принудительно выделить выделение внутри подпрограммы?

Я буду признателен за ваши комментарии. Привет, Эдуардо


person Jauch    schedule 29.12.2014    source источник


Ответы (1)


В конструкции типа select (или ассоциирования) ассоциированное имя никогда не имеет распределяемого атрибута (16.5.1.6p2), независимо от того, есть ли этот атрибут у выбора.

В вашем случае в селекторе также отсутствует этот атрибут - фиктивный аргумент value не объявляется выделяемым. Вам не разрешено связывать нераспределенный фактический аргумент с необязательным нераспределяемым фиктивным аргументом. Кроме того, вам не разрешено использовать нераспределенный селектор в типе выбора или ассоциированной конструкции.

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

person IanH    schedule 29.12.2014
comment
Спасибо за объяснение, @IanH. Я добавлю возможность использовать созданный мной производный тип (строку), но оставлю возможность использовать строку с учетом того, что она должна быть выделена перед передачей в качестве аргумента подпрограмме. - person Jauch; 29.12.2014