Как объявить раздел интерфейса для аргумента процедуры, который, в свою очередь, ссылается на пользовательский тип того же модуля? - PullRequest
1 голос
/ 18 декабря 2011

Как показано в следующем примере кода, person_list является производным от пользователя типом и содержит связанную с типом процедуру compare_persons. Я бы хотел, чтобы compare_persons мог принять определенную группу compareFunc в качестве одного из аргументов и поэтому объявить раздел интерфейса для compareFunc. Обратите внимание, что первый аргумент compareFunc имеет тип person_list. (Как вы могли бы сказать, person_list походит на TStringList в VCL Delphi.)

Компиляция не может быть продолжена. Сообщения об ошибках:

[root@localhost new]# ifort -c lib1.f90 
lib1.f90(26): error #6457: This derived type name has not been declared.   [PERSON_LIST]
                    TYPE(person_list) :: persons    !   error #6457: This derived type name has not been declared.   [PERSON_LIST]
-------------------------^
lib1.f90(23): error #6404: This name does not have a type, and must have an explicit type.   [PERSONS]
                FUNCTION compareFunc(persons, index1, index2)    !   error #6404: This name does not have a type, and must have an explicit type.   [PERSONS] 
-------------------------------------^
compilation aborted for lib1.f90 (code 1)

Сообщения об ошибках, кажется, указывают на круговую ссылку между модулями? Поэтому мне интересно, как объявить раздел интерфейса для аргумента процедуры, который, в свою очередь, ссылается на пользовательский тип того же модуля? Любые идеи будут оценены!

PS: причина попробовать этот модуль - предпочтение стиля программирования ОО. Причиной использования Fortran является большая кодовая база.

PS: Компилятор - Intel Fortran Compiler, и версия выглядит следующим образом:

[root@localhost new]# ifort --version
ifort (IFORT) 12.1.0 20111011
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.

Пример кода:

MODULE lib1

    TYPE person_list

    CONTAINS
        PROCEDURE, PASS :: compare_persons

    END TYPE

CONTAINS

    FUNCTION compare_persons(this, index1, index2, compareFunc)

        IMPLICIT NONE

        INTEGER :: compare_persons
        CLASS(person_list) :: this
        INTEGER, INTENT(IN) :: index1
        INTEGER, INTENT(IN) :: index2

        INTERFACE
            FUNCTION compareFunc(persons, index1, index2)    !   error #6404: This name does not have a type, and must have an explicit type.   [PERSONS] 
                IMPLICIT NONE
                INTEGER :: compareFunc
                TYPE(person_list) :: persons    !   error #6457: This derived type name has not been declared.   [PERSON_LIST]
                INTEGER :: index1
                INTEGER :: index2
            END FUNCTION compareFunc
        END INTERFACE

        compare_persons = compareFunc(this, index1, index2)

    END FUNCTION compare_persons

END MODULE lib1

tpg2114 выясняет решение!

MODULE lib1

    TYPE person_list

    CONTAINS
        PROCEDURE, PASS :: compare_persons

    END TYPE

    INTERFACE
        FUNCTION CompareFuncInterface(persons, index1, index2)  
            IMPORT person_list
            IMPLICIT NONE
            INTEGER :: CompareFuncInterface
            TYPE(person_list), INTENT(IN) :: persons    
            INTEGER, INTENT(IN) :: index1
            INTEGER, INTENT(IN) :: index2
        END FUNCTION CompareFuncInterface
    END INTERFACE

CONTAINS

    FUNCTION compare_persons(this, index1, index2, compareFunc)

        IMPLICIT NONE

        INTEGER :: compare_persons
        CLASS(person_list), INTENT(IN) :: this
        INTEGER, INTENT(IN) :: index1
        INTEGER, INTENT(IN) :: index2
        PROCEDURE (CompareFuncInterface) :: compareFunc

        compare_persons = compareFunc(this, index1, index2)

    END FUNCTION compare_persons

END MODULE lib1

1 Ответ

5 голосов
/ 18 декабря 2011

Хорошо, я понял это:

MODULE lib1

   TYPE :: persons
   CONTAINS
      PROCEDURE, PASS :: compare_persons
   END TYPE persons

   INTERFACE
      INTEGER FUNCTION compareFunc_interface(personsIn, index1, index2)
         IMPORT persons
         IMPLICIT NONE
         TYPE(persons), INTENT(IN) :: personsIn
         INTEGER, INTENT(IN) :: index1
         INTEGER, INTENT(IN) :: index2 
      END FUNCTION compareFunc_interface
   END INTERFACE


CONTAINS 
   FUNCTION compare_persons(this, index1, index2, compareFunc)
      IMPLICIT NONE

      INTEGER :: compare_persons
      CLASS(persons) :: this
      INTEGER :: index1
      INTEGER :: index2
      PROCEDURE(compareFunc_interface) :: compareFunc
   END FUNCTION compare_persons
END MODULE lib1

Из стандарта 2003 оператор IMPORT переносит определение из области определения узла в локальную область определения.Если бы вы использовали что-то из другого модуля, для INTERFACE потребуется оператор USE.Но так как вы импортируете из верхней области видимости, вы используете IMPORT и список вещей, которые вы хотели бы внести в эту область

Edit

Также обратите внимание, я добавил PASS к объявлению процедуры с привязкой к типу.Хотя это и не обязательно (поскольку это действие по умолчанию), я предпочитаю всегда ставить PASS или NOPASS, чтобы намерение всегда было явным.Это помогает как программисту (убедившись, что он делает то, что он думает), так и любому, кто читает код.

...