Подмодули Fortran, использующие один и тот же интерфейс - PullRequest
0 голосов
/ 21 марта 2019

Я думаю об использовании функции субмодулей в Фортране и настроил небольшой тестовый пример.У меня есть два вопроса, связанных с их использованием.Ниже приведен пример кода:

module points
    type :: point
        real :: x, y
    end type point

    interface
        module function point_dist(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function point_dist
    end interface
end module points

submodule (points) points_a

contains
    module procedure point_dist
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist

end submodule points_a

Это работает, и в моей программе я могу просто использовать его следующим образом:

program test

    use points

    real(kind(1.0D0)) :: result
    type (point) :: p1, p2

    p1%x = 1
    p1%y = 1

    p2%x = 2
    p2%y = 2

    result = point_dist(p1, p2)

    write(*,*) result

end program test

Вопросы

1) Однако мне было интересно, возможно ли иметь два подмодуля, которые используют один и тот же интерфейс, но обеспечивают разные результаты.Это имеет некоторое применение, когда у нас есть разные формулы для расчета одной и той же физической величиныНиже я представляю, как это будет работать, даже если это не так.

module points
    type :: point
        real :: x, y
    end type point

    interface
        module function point_dist(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function point_dist
    end interface
end module points

submodule (points) points_a

contains
    module procedure point_dist
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist

end submodule points_a

submodule (points) points_b

contains
    module procedure point_dist
        distance = 2.0*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist

end submodule points_b

Я получаю сообщение об ошибке в программе, поскольку у меня есть только утверждение use points, и оно жалуется на дублирующиеся определения point_dist,Можно ли указать, какой подмодуль я хочу использовать?

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

module points
    type :: point
        real :: x, y
    end type point

    interface
        module function point_dist(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function point_dist
    end interface
end module points

submodule (points) points_a

contains
    module procedure (type=point_dist) point_dist_a
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_a

    module procedure (type=point_dist) point_dist_b
        distance = 2.0*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_b

end submodule points_a

Хотя я понимаю, что это может привести к некоторому вводящему в заблуждение и сложному для понимания коду.

(я использую gfortran 8.3.0на OS X)

1 Ответ

2 голосов
/ 21 марта 2019

1) Однако мне было интересно, возможно ли иметь два подмодуля, которые используют один и тот же интерфейс, но обеспечивают разные результаты.Это имеет некоторое применение, когда у нас есть разные формулы для расчета одной и той же физической величины.

Если бы это было возможно, как вы планируете использовать его?Я имею в виду, что если у вас есть две разные реализации, доступные для функции point_dist, которая может дать разные результаты, вы бы не захотели их несовместить, не так ли?

Если вы хотите, чтобы они имели одинаковое имя,Вы (и компилятор) должны быть в состоянии определить, какой из них вы вызываете.Обычно это делается с перегрузкой функции .В Фортране у вас может быть generic interface.НО отправляемые функции ДОЛЖНЫ различаться по своему интерфейсу (типы аргументов и / или количество, позиция, среди прочих правил).Вы знаете, как кто-то еще узнает, что из двух вы имеете в виду?

2) Я также посмотрел, но не смог выяснить, возможно ли использовать один и тот же интерфейс уровня модуля для различных процедурвнутри одного и того же подмодуля.

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

module points
    type :: point
        real :: x, y
    end type point

    interface point_dist
        module function point_dist_a(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function
        module function point_dist_b(a, b, k) result(distance)
            type(point), intent(in) :: a, b
            real, intent(in) :: k
            real :: distance
        end function
    end interface
end module points

submodule (points) points_a

contains
    module procedure point_dist_a
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_a

end submodule points_a

submodule (points) points_b

contains
    module procedure point_dist_b
        distance = k*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_b

end submodule points_b

Тестирование:

program test

    use points

    real(kind(1.0D0)) :: result
    type (point) :: p1, p2

    p1%x = 1
    p1%y = 1

    p2%x = 2
    p2%y = 2

    result = point_dist(p1, p2)
    write(*,*) result

    result = point_dist(p1, p2, 2.0)
    write(*,*) result

end program test

В заключение, submodules не имеет абсолютно ничего общего со всем этим.

...