我创建了一个派生类型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
答案 0 :(得分:2)
让我们看一下子程序vsum
。在该子例程中完成的工作取决于所有三个对象ta
,tb
和tc
的组件的定义。为了使您的求和按预期继续进行,必须分配所有可分配组件,并使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.
现在,a
是vadd
的功能结果。因此,就像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
作为引号中的实际参数。