Процедура с привязкой к типу выдает ошибку о неполиморфном фиктивном аргументе переданного объекта

Я пытаюсь скомпилировать модуль Fortran ниже (используя gfortran 7.2.0). Суть в том, чтобы определить производный тип, который, в свою очередь, содержит два экземпляра производного типа bspline_3d из библиотеки bspline-fortran (https://github.com/jacobwilliams/bspline-fortran). Затем я хочу определить процедуру с привязкой к типу, которая, в свою очередь, будет вызывать процедуру с привязкой к типу evaluate обоих этих типов и возвращать результат в виде массива с двумя элементами.

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

     procedure  :: evaluate => evaluate_2d
             1
Error: Non-polymorphic passed-object dummy argument of 'evaluate_2d' at (1)

Я абсолютно ничего не понимаю в сообщении об ошибке.

Мне удалось скомпилировать простой пример программы, который можно найти здесь: http://fortranwiki.org/fortran/show/Object-Oriented+programming и, насколько я могу судить, единственная разница в том, что в моем случае "переданный объект" (this) сам имеет переменные-члены производного типа (type(bspline_3d) :: fvx, fvy), которые в свою очередь, вероятно, содержат всякую всячину.

module interpolator_module

use bspline_module
use parameters, only: WP

implicit none

private
public :: interpolator

type :: interpolator
    type(bspline_3d) :: fvx, fvy
    contains
        private
        procedure  :: evaluate => evaluate_2d
end type interpolator

contains
    function evaluate_2d(this, X, t) result(V)
        implicit none
        ! inputs
        type(interpolator),     intent(inout) :: this
        real(WP), dimension(2), intent(in)    :: X
        real(WP),               intent(in)    :: t
        ! output
        real(WP), dimension(2)                :: V
        ! local variables
        integer                               :: iflag
        integer, parameter                    :: d = 0

        call this%fvx%evaluate(X(1), X(2), t, d, d, d, V(1), iflag)
        call this%fvy%evaluate(X(1), X(2), t, d, d, d, V(2), iflag)
    end function
end module interpolator_module

person Tor    schedule 21.01.2018    source источник


Ответы (2)


Для процедуры с привязкой к типу, определенной как

type my_type
 contains
  procedure :: proc
end type

процедура с привязкой к типу имеет переданный аргумент. То есть, когда

type(my_type) my_obj
call my_obj%proc

используется, объект my_obj находится в списке аргументов. С proc определенным как

subroutine proc(me)
  type(my_type) me   ! Not correct
end subroutine

тогда call my_obj%proc похоже на call proc%(my_obj).1 Это часть сообщения об ошибке, связанная с "фиктивным аргументом переданного объекта".

В приведенном выше определении proc фиктивный аргумент переданного объекта type(my_type) me не является полиморфным. Вы можете прочитать о полиморфизме в другом месте, но чтобы ответить на вопрос: фиктивный аргумент переданного объекта не может быть неполиморфным. Он должен быть полиморфным, объявленным с использованием class(my_type) me:

subroutine proc(me)
  class(my_type) me   ! Polymorphic, declared type my_type
end subroutine

Это означает, что может быть передан объект типа my_type или типа, расширяющего my_type. Это требование языка Фортран.

Короче: меняй

type(interpolator),     intent(inout) :: this

to

class(interpolator),     intent(inout) :: this

Ситуация усложняется тем, что старые версии gfortran, например, понимали процедуры привязки типов раньше, чем понимали полиморфизм. Это означает, что есть несколько примеров ошибочного использования неполиморфных переданных объектов.


1 Я намеренно оставил имя привязки proc таким же, как и имя процедуры. В контексте вопроса это будет call my_obj%evaluate(...) как call evaluate_2d(my_obj, ...).

person francescalus    schedule 21.01.2018

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

 class(interpolator),     intent(inout) :: this

и не

 type(interpolator),     intent(inout) :: this

Это фундаментальное требование для процедур с привязкой к типу. В противном случае вы не могли бы использовать процедуру для расширенных типов (дочерних).

person Vladimir F    schedule 21.01.2018