使用 gfortran (gcc8) 比较两个派生类型变量

Compare two derived type variables using gfortran (gcc8)

我有以下派生类型:

type datetime
    integer     :: year
    integer     :: month
    integer     :: day
    integer     :: hour
    integer     :: minute
end type

我用这种类型定义了两个变量:

type(datetime)                          :: session_end
type(datetime)                          :: session_cursor

我正在尝试比较这两个变量,以查看派生类型元素是否具有相同的值。

do while (session_cursor /= session_end)
    ...
end do

但我得到:

do while (session_cursor /= session_end)
         1
Error: Operands of comparison operator '/=' at (1) are TYPE(datetime)/TYPE(datetime)

我在 FreeBSD 12 64 位下使用 gfortran (gcc8)

我用 gfortran 进行了检查,但我收到了相同的错误消息。如果比较日期时间的各个变量,代码将起作用。 可能您必须使用重载,因为没有为您的类型定义比较。检查此示例,了解如何重载我发现 https://courses.physics.illinois.edu/phys466/sp2013/comp_info/overload.html

当涉及到操作时,例如这里需要的比较操作,有两种截然不同的类型:固有操作和定义操作.

内部操作是编译器 'knows about by default' 的操作,定义的操作是由代码 compiled/used 提供的操作。

仅为内部类型提供内部比较操作。对于内在一元运算符(如一元减-),操作数必须是内在类型;对于内部二元运算符,两个操作数都必须是内部类型。

即使是等式和不等式,派生类型也必须使用定义的操作。该问题的错误消息是说编译器没有这样定义的操作 known/accessible 。其他编译器可能会给出诸如

之类的消息

error #6355: This binary operation is invalid for this data type.

Operands to .NE. operator are of derived type

1511-026 (S) Type of operand is not permitted for comparison operation.

因为没有可用的定义操作,编译器只能将派生类型视为内部操作的操作数 - 这是不允许的。

为了提供定义的操作,我们首先提供一个函数。对于此函数来说,return 一个 true/false 值是有意义的,采用此派生类型的两个操作数,而不是修改它们:

logical function datetime_unequal(lhs, rhs)
   class(datetime), intent(in) :: lhs, rhs
   datetime_unequal = ...   ! Implement inequality test
end function datetime_unequal

我们可以以明显的方式使用这个函数(而不是作为运算符):

do while (datetime_unequal(session_cursor, session_end)))
...
end do

这可能足以满足许多目的,但我们可以继续我们的方法来进行定义的比较操作。 (为了保持一致性,我们将调用我们的运算符 /=。)我们通过提供通用接口或通用绑定重载 operator(/=).

来实现这一点

考虑

module datetime_mod
  implicit none

  type datetime
    ...
  contains
    procedure datetime_unequal
    ! A generic binding
    generic :: operator(/=) => datetime_unequal
  end type

! A generic interface
  interface operator(/=)
    module procedure datetime_unequal 
  end interface

contains

  logical function datetime_unequal(lhs, rhs)
    class(datetime), intent(in) :: lhs, rhs
    datetime_unequal = ...   ! Implement inequality test
  end function datetime_unequal

end module datetime_mod

请注意,您无需同时提供通用接口和通用绑定。事实上,在大多数情况下,泛型绑定(在类型定义中定义)更可取:只要类型定义本身可访问,它就可以访问;通用接口具有独立的可访问性。

另请注意,比较函数的参数是多态的 (class(datetime)),以允许将其用作类型绑定过程。使用独立功能就没有必要了。

最后,大部分讨论都适用于更一般的(二进制)操作,而不仅仅是那些重载内部操作的操作。