首页 > 解决方案 > 使用 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)

标签: fortrangfortranfortran90

解决方案


说到操作,比如这里需要的比较操作,有两种不同的类型:内在操作和定义操作。

内在操作是编译器“默认知道”的操作,而定义的操作是由正在编译/使用的代码提供的操作。

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

即使对于相等和不等,定义的操作也必须用于派生类型。该问题的错误消息是说编译器不知道/无法访问此类定义的操作。其他编译器可能会给出消息,例如

错误 #6355:此二进制操作对此数据类型无效。

或者

.NE 的操作数。运算符属于派生类型

或者

1511-026 (S) 操作数类型不允许用于比较运算。

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

为了提供定义的操作,我们首先提供一个函数。这个函数返回一个真/假值是有意义的,它采用这个派生类型的两个操作数,而不是修改它们:

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)) 以允许将其用作类型绑定过程。使用独立功能,这将不是必需的。

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


推荐阅读