fortran - 使用 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)
解决方案
说到操作,比如这里需要的比较操作,有两种不同的类型:内在操作和定义操作。
内在操作是编译器“默认知道”的操作,而定义的操作是由正在编译/使用的代码提供的操作。
仅对固有类型提供固有比较操作。对于内在一元运算符(例如一元减号-
),操作数必须是内在类型;对于内在二元运算符,两个操作数都必须是内在类型。
即使对于相等和不等,定义的操作也必须用于派生类型。该问题的错误消息是说编译器不知道/无法访问此类定义的操作。其他编译器可能会给出消息,例如
错误 #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)
) 以允许将其用作类型绑定过程。使用独立功能,这将不是必需的。
最后,这个讨论的大部分内容适用于更一般的(二进制)操作,而不仅仅是那些重载内在操作的操作。
推荐阅读
- c++ - 为什么“新”只创建一个对象而不是一组对象?
- javascript - 是否有示例显示如何通过 websockets 发送图像?
- snowflake-cloud-data-platform - 找出雪花过程中引用的对象列表
- php - 为什么 ob_flush 在 apache localhost 上工作而不是远程工作?
- r - 如何在具有可反应的数字参数的同一向量中引入非数字参数?
- css - 如何在 tailwind-css 中自定义容器宽度?
- mysql - JSON_EXTRACT 在存储过程中总是返回 null
- python - Python-docx:ValueError:要解包的值太多(预期为 2)
- vb.net - Microsoft Graph SendMail 返回 ErrorInternalServerError
- azure - 获取 azure 订阅属于什么类型,例如 Pay As you Go、MCA、EA、CSP