Незаконное использование производного типа с вызовом функции - PullRequest
1 голос
/ 24 октября 2011

У меня есть простая функция, которая возвращает объект времени на основе строки времени:

FUNCTION getTime(timeStr)RESULT(time)
IMPLICIT NONE
CHARACTER(LEN=19),INTENT(IN) :: timeStr
TYPE timeType
 INTEGER :: yyyy,mo,dd,hh,mm,ss
ENDTYPE timeType
TYPE(timeType) :: time
READ(UNIT=timeStr( 1: 4),'(I4)')time%yyyy
READ(UNIT=timeStr( 6: 7),'(I2)')time%mo
READ(UNIT=timeStr( 9:10),'(I2)')time%dd
READ(UNIT=timeStr(12:13),'(I2)')time%hh
READ(UNIT=timeStr(15:16),'(I2)')time%mm
READ(UNIT=timeStr(18:19),'(I2)')time%ss
ENDFUNCTION getTime

Я называю это из родительской процедуры как:

umwmTime1=getTime(umwmStartTimeStr)
umwmTime2=getTime(umwmStopTimeStr)

, где umwmTime 1 и 2 объявлены как:

TYPE timeType
  INTEGER :: yyyy,mo,dd,hh,mm,ss
ENDTYPE timeType
TYPE(timeType) :: umwmTime1,umwmTime2

Я получаю сообщение об ошибке компиляции:

PGF90-S-0099-Illegal use of derived type (ESMF_interface_UMWM.F90: 282)
PGF90-S-0099-Illegal use of derived type (ESMF_interface_UMWM.F90: 283)
  0 inform,   0 warnings,   2 severes, 0 fatal for umwm_component_run

Строки 282 и 283 точки являются вызовами функций в родительской подпрограмме.

Однако, если я использую подпрограмму (вместо функции), чтобы получить umwmTime1 и umwmTime2 в качестве аргументов INTENT (OUT), у меня не возникнет проблем. Что я делаю не так с функцией?

Ответы [ 2 ]

6 голосов
/ 25 октября 2011

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

Например, в простой однофайловой программе предоставленный вами код не работает для меня в gfortran,но это делает:

MODULE timeTypeDef
TYPE timeType
    INTEGER :: yyyy,mo,dd,hh,mm,ss
ENDTYPE timeType
END MODULE timeTypeDef

PROGRAM foo
USE timeTypeDef
IMPLICIT NONE

TYPE(timeType) :: umwmTime1, umwmTime2

umwmTime1=getTime('2010-10-10-14:39:03')
umwmTime2=getTime('2011-11-11-09:17:53')

contains

FUNCTION getTime(timeStr)RESULT(time)
    USE timeTypeDef
    IMPLICIT NONE
    CHARACTER(LEN=19),INTENT(IN) :: timeStr
    TYPE(timeType) :: time

    READ(UNIT=timeStr( 1: 4),FMT='(I4)')time%yyyy
    READ(UNIT=timeStr( 6: 7),FMT='(I2)')time%mo
    READ(UNIT=timeStr( 9:10),FMT='(I2)')time%dd
    READ(UNIT=timeStr(12:13),FMT='(I2)')time%hh
    READ(UNIT=timeStr(15:16),FMT='(I2)')time%mm
    READ(UNIT=timeStr(18:19),FMT='(I2)')time%ss
ENDFUNCTION getTime

END PROGRAM foo
0 голосов
/ 24 октября 2011

Поместите вашу функцию "getTime" в модуль и используйте этот модуль в вызывающей подпрограмме.

Проблема заключается в том, что вызывающая подпрограмма не знает, что подпрограмма getTime возвращает TYPE (timeType).По умолчанию getTime рассматривается как реальное скалярное значение.Следовательно, вам нужен явный интерфейс, который легко предоставляется оператором USE.Этот интерфейс также может быть предоставлен блоком INTERFACE, но это не рекомендуется, так как подвержен ошибкам.

Я также хотел бы отметить, что объявление CHARACTER (len = 19) аргумента timeStr очень опасно,Вместо этого я предлагаю:

FUNCTION getTime(timeStr)RESULT(time)
IMPLICIT NONE
CHARACTER(LEN=*),INTENT(IN) :: timeStr
...

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

...