Fortran 命名运算符

Fortran named operator

我编写了一个派生类型并为其定义了一个命名运算符,如下所示:

module ModuleNamedOperator
  implicit none
  type TCoords
    contains
      procedure :: TCoordsFM
      generic,public :: operator(.fm.) => TCoordsFM
  end type
  contains
    type(TCoords) function TCoordsFM(self,IVal) result(this)
      class(TCoords),intent(in) :: self
      integer(4),intent(in) :: IVal
      this=self
      write(*,'(I0)') "IVal:",IVal
    end function TCoordsFM
end module ModuleNamedOperator

当我尝试在以下代码中使用它时,发生了一些奇怪的事情:

program test
  use ModuleNamedOperator
  implicit none
  type(TCoords) :: a
  integer(4) :: i
  i=1
  a=a .fm. 1              ! Case 1, valid
  a=a .fm. i              ! Case 2, valid
  a=a .fm. 1 .fm. i       ! Case 3, invalid
  a=a .fm. i .fm. 1       ! Case 4, valid
  a=a .fm. 1 .fm. 1       ! Case 5, valid
  a=a .fm. i .fm. i       ! Case 6, invalid
end program test

在案例 3 和案例 6 中,代码无效。似乎如果运算符.fm 的第二个参数。是一个变量或一个命名常量,那么就会发生错误。那么这些案件是怎么回事呢?还有出路吗?如果重要的话,编译器是 ifort_2013_sp1.3.174。 编译器给出以下错误消息:

TestNamedOperator.f90(25): error #6866: Dotted string neither a defined operator nor a structure component   [FM]
  a=a .fm. 1 .fm. i
--------------^
TestNamedOperator.f90(28): error #6866: Dotted string neither a defined operator nor a structure component   [FM]
  a=a .fm. i .fm. i
--------------^
TestNamedOperator.f90(25): error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands.
  a=a .fm. 1 .fm. i
-------------^
TestNamedOperator.f90(28): error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands.
  a=a .fm. i .fm. i
-------------^
compilation aborted for TestNamedOperator.f90 (code 1)

我认为您遇到了 ifort 编译器错误,请参阅 here。将 write 语句更改为 write(*,'(A,I0)') "IVal:",IVal 时,您的代码可以使用 gfortran 正常编译。

对于 ifort,显式调用函数有帮助:

program test
  use ModuleNamedOperator
  implicit none
  type(TCoords) :: a
  integer(4) :: i
  i=1
  a=a .fm. 1              ! Case 1, valid
  a=a .fm. i              ! Case 2, valid
  a=TCoordsFM((a .fm. 1), i)      ! Case 3, valid
  a=TCoordsFM((a .fm. i), 1)      ! Case 4, valid
  a=TCoordsFM((a .fm. 1), 1)      ! Case 5, valid
  a=TCoordsFM((a .fm. i), i)      ! Case 6, valid
end program test