Передача функций, которые имеют производные типы в качестве аргументов, в качестве аргументов в Fortran - PullRequest
3 голосов
/ 02 октября 2019

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

Я попытался скомпилировать приведенный ниже код с помощью gfortran 9. Сбой выдает сообщение об ошибке:

   47 |         call funA(x, y, baz)
      |                        1
Error: Interface mismatch in dummy procedure ‘baz’ at (1): Type mismatch in argument 'y' (CLASS(foo)/CLASS(bar))

Различные другие попытки замены foo на bar приводят к аналогичным результатам. Использование pgfortran 19.4 приводит к той же ошибке.

module A
    implicit none
    private

    type, abstract, public :: foo
    end type foo

    public :: funA

contains

    subroutine funA(x, y, baz)
        integer, intent(in)    :: x
        class(foo), intent(in) :: y
        interface
            function baz(x, y) result(z)
                import foo
                integer,    intent(in) :: x
                class(foo), intent(in) :: y
                integer                :: z
            end function baz
        end interface

        write(*,*) baz(x, y)
    end subroutine funA

end module

module B
    use A
    implicit none
    private

    type, extends(foo), public :: bar
        integer :: ii
    end type bar

    public :: fiz

contains

    function baz(x, y) result(z)
        integer,    intent(in) :: x
        class(bar), intent(in) :: y
        integer :: z

        z = x + y%ii
    end function baz

    subroutine fiz(x, y)
        integer,    intent(in) :: x
        class(bar), intent(in) :: y

        call funA(x, y, baz) ! <---- This causes errors.
    end subroutine fiz
end module

program meh
    use B
    implicit none
    integer   :: x
    type(bar) :: y
    x = 1
    y%ii = 2
    call fiz(x, y)
end program meh

Я ожидал бы, что, поскольку y имеет тип bar, он также имеет тип foo, и поэтому я могу передать его в funA. Функция baz должна знать, что y имеет тип bar, иначе она не может получить доступ к ii. Однако остальной код не должен знать об этом, не так ли?

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

1 Ответ

3 голосов
/ 03 октября 2019

Указанная здесь ошибка заключается в характеристиках аргумента процедуры. Пустой аргумент процедуры baz из funA имеет характеристики, которые не соответствуют фактическому аргументу процедуры baz модуля B. Пустой аргумент имеет второй аргумент (y) объявленного типа foo, тогда как переданная ему процедура baz имеет соответствующий аргумент объявленного типа bar.

Это несоответствие не допускаетсяв характеристиках в фиктивных и фактических аргументах процедуры.

Чтобы решить эту проблему, необходимо сделать фиктивные аргументы y для фиктивной baz и модульной процедуры baz одного и того же объявленного типа (вероятно foo). Конечно, вам нужно будет обойтись без y в baz (модуля B) с объявленным типом foo: такой y не имеет компонента ii. Быстрый взлом состоит в использовании конструкции select type, но вполне могут быть и другие подходы, если можно спроектировать другой поток.


Как видите, часто помогают обсуждения такого кода. если различные аргументы и тому подобное имеют разные имена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...