Fortran子模块共享相同的接口

问题描述 投票:0回答:1

我正在考虑在Fortran中使用子模块功能,并设置了一个小的测试示例。我有两个与其用法有关的问题。以下是示例代码:

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

Questions

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

虽然我意识到这可能导致一些非常误导和难以遵循的代码。

(我在OS X上使用gfortran 8.3.0)

fortran gfortran
1个回答
2
投票

1)但是我想知道是否有可能有两个使用相同接口但提供不同结果的子模块。这有一些用途,我们有不同的公式来计算相同的物理量。

如果这是可能的,你是如何计划使用它的?我的意思是,如果你有两个不同的实现可用于功能point_dist thay可能产生不同的结果,你不会想要它们不匹配,是吗?

如果您希望它们具有相同的名称,您(和编译器)必须能够识别您正在呼叫的那个。这通常通过函数重载完成。在Fortran,你可能有一个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与这一切完全无关。

© www.soinside.com 2019 - 2024. All rights reserved.