【问题标题】:Passing functions, which have derived types as arguments, as arguments in Fortran将派生类型作为参数的函数作为 Fortran 中的参数传递
【发布时间】:2019-10-02 20:46:52
【问题描述】:

我有一个子程序,它接收一些数据和另一个函数作为参数。该函数可以将此数据作为参数。子程序就是用给定的数据调用这个函数。现在让我们假设数据可以是 foo 类型。我假设我也可以传递 from foo 派生类型 bar 的数据。显然 Fortran 不同意。

我尝试使用 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))

用 bar 替换 foo 的各种其他尝试产生了类似的结果。使用 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。但是其余的代码实际上并不需要知道这一点,不是吗?

我的推理错误在哪里?怎样才能让上面的代码编译运行?

【问题讨论】:

    标签: fortran


    【解决方案1】:

    这里指出的错误在于过程参数的特性。 funA 的过程虚拟参数baz 具有与模块B 的过程实际参数baz 不匹配的特性。虚拟参数具有声明类型为foo 的第二个参数(y),而传递给它的过程baz 具有声明类型为bar 的相应参数。

    不允许在虚拟和实际过程参数中出现这种不匹配的特性。

    要解决这个问题,必须使虚拟baz 的虚拟参数y 和模块过程baz 具有相同的声明类型(可能是foo)。当然,您需要解决在声明类型foobaz(模块B)中的y:这样的y 没有组件ii。一个快速的技巧是使用select type 构造,但如果可以设计不同的流程,很可能还有其他方法。


    如您所见,如果各种参数等具有不同的名称,则通常有助于围绕此类代码进行讨论。

    【讨论】:

      猜你喜欢
      • 2014-04-11
      • 2017-08-14
      • 2015-12-09
      • 2018-01-04
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      • 2011-06-03
      • 2013-08-02
      相关资源
      最近更新 更多