Fortran:从函数的返回类型访问值

时间:2016-05-25 01:46:22

标签: fortran operator-overloading

我创建了一个派生类型V,并包含了一个add函数 这样我就可以使用operator +。

但是当我这样做时

z = u + v

未执行操作。我认为这是因为z%kn 没有被访问。

但是当我这样做时

Call vsum(z, u, v) 

一切都按预期工作

下面是派生类型的声明和 重载函数vadd。

Module vtest

Type :: V

  Character (Len=8) :: kn
  Real,  Allocatable :: vc(:)

  Contains

    Procedure :: vadd
    Generic :: Operator (+) => vadd

 End Type vtest

Contains

Function vadd (b, c) Result (a)
  Type (V) :: a
  Class (V), Intent (In) :: b, c

  !!$ In vsum, use is made of a% kn 
  Call vsum (a, b, c)

End Function vadd

 Subroutine vsum (ta, tb, tc)
   Type (V), Intent (InOut)  :: ta
   Type (V), Intent (In) :: tb, tc

   Logical :: la, lb, lc

   la = .False.;  lb = .False.;  lc = .False.

   Select Case (ta%kn) 

   Case ("Real32")
     If (Allocated (ta%vc)) la = .True.
     If (Allocated (tb%vc)) lb = .True.
     If (Allocated (tc%vc)) lc = .True.
     If (la .And. lb .And. lc) Then 
       ta%vc = tb%vc + tc%vc
     End If

   End Select

 End Subroutine vsum

End Module vtest


Program test
Use vtest
Type (V) :: z

   z% kn = "Real32"
   Allocate (z% vc_real32(3))
   Write (*,*) "z = u + v"
   Write (*,*) "z% kn: ", z% kn
   z = u + v
   Write (*,*) "z% kn: ", z% kn
   Write (*,*) "z: ", z% vc_real32

End Program vtest

1 个答案:

答案 0 :(得分:2)

让我们看一下子程序vsum。在该子例程中完成的工作取决于所有三个对象tatbtc的组件的定义。为了使您的求和按预期继续进行,必须分配所有可分配组件,并使ta%kn'Real32'匹配。

没有完整的工作示例,但正如你所说的那样,当有像

这样的电话时,情况有效
call vsum(z, u, w)  ! V is the name of the type, so call the variable w

z%kn设置为'Real32'

但是,使用定义的操作

z = u + w

有功能参考

z = vadd(u, w)

其中有电话

call vsum (a, b, c)  ! Actual arguments "z", u, w.

现在,avadd的功能结果。因此,就像intent(out) a的伪参数最初未定义一样。

这意味着,基本上,当通过vadd z时,使用未定义的组件vsum和未分配的组件kn使其成为vc。因此,不满足求和的要求(实际上select case形成无效的引用)。

我想我也可以评论如何解决这个问题。

vsum中,您实际上是从“结果”中获取操作类型。相反,像

Subroutine vsum (ta, tb, tc)
  Type (V), Intent (Out)  :: ta
  Type (V), Intent (In) :: tb, tc

  Logical :: lb, lc

  lb = .False.;  lc = .False.

  ! In here we probably want some consistency checking...
  Select Case (tb%kn)    
  Case ("Real32")
    If (Allocated (tb%vc)) lb = .True.
    If (Allocated (tc%vc)) lc = .True.
    If (lb .And. lc) Then 
      ta%vc = tb%vc + tc%vc   ! ta%vc being automatically allocated
    End If
  End Select

 End Subroutine vsum

这自然不会解决你从结果中采取操作类型的看似愿望(从标题中)。 可以使用原始子例程方法执行此操作,但在一个不是Fortran函数原理的实例中除外。

如果要使用已定义的操作,则无法通过赋值的左侧定义操作。在表达式u+w中没有左侧,但仍然期望定义的操作表现出来。也就是说,在声明中

z = u + w

您并不是说“z是应用于+u的操作w的结果”。但是:“评估应用于+u的操作w,并将结果(通过定义或隐式分配)分配给z”。在达到“结果类型”之前有分配。这就是为什么我之前将z作为引号中的实际参数。