过程和运算符重载

在实际的函数编写过程中,有时候需要涉及多重类型,不同维度的数组。我们通常希望提供更加简单一致的接口,方便调用,这时候就需要用到重载。

过程重载

使用interface就可以对相关的过程进行重载

Fortran 2018引入了generic关键字,也可以对函数进行重载,语法大大简化(gfortran不支持,ifx,flang支持)

! src/add_mod.f90
module add_mod
  implicit none
  interface add
    module procedure add_int
    module procedure add_real
  end interface
  ! Fortran 2018 与上面四句等价
  !generic::add=>add_int,add_real
contains
  elemental integer function add_int(a,b)result(c)
    integer,intent(in)::a,b
    c=a+b
  end function add_int
  elemental real function add_real(a,b)result(c)
    real,intent(in)::a,b
    c=a+b
  end function add_real
end module add_mod
! app/main.f90
program main
  use add_mod
  write(*,*)add(1,2)
  write(*,*)add(1.0,2.0)
  !write(*,*)add(1.0,2) !错误 报错的一般形式为 no specific function for the generic 'add' 
 
end program main
$ fpm run
           3
   3.00000000 

如果使用generic语法,则使用fpm run --compiler ifort

运算符重载

对内置的运算符进行重载,有时候可以提高代码的一致性。

module add_mod
  implicit none
  interface operator(+)
    module procedure add_str
  end interface
  ! Fortran 2018 与上面等价
  !generic::operator(+)=>add_str
contains
  function add_str(a,b)result(c)
      character(len=*),intent(in)::a
      character(len=*),intent(in)::b
      character(len=:),allocatable::c
      c=trim(a)//","//trim(b)
  end function add_str
end module add_mod

program main
  use add_mod
  write(*,*)'"',"hello   "+"world ",'"'
end program main
$ fpm run
 "hello,world"
  • 运算符重载有时候会写出比较含糊的代码,建议要谨慎使用。
  • 不可以对运算符二次重载,例如我们无法对整数的加法再进行重载

自定义运算符

除了内置的运算符之外,Fortran也支持自定义运算符,使用两个点.作为标记,例如我们之前接触的.lt.,.ge.

module find_mod
  implicit none
  interface operator(.in.)
    module procedure find
  end interface
  ! Fortran 2018 与上面等价
  !generic::operator(.in.)=>find
contains
  logical function find(v,a)result(res)
      integer,intent(in)::v
      integer,intent(in)::a(:)

      integer::i
      res=.false.
      do i=1,size(a)
        if(a(i)==v)then
          res=.true.
          return
        end if
      end do
  end function  find
end module find_mod

program main
  use find_mod
  write(*,*) 1 .in. [1,2,3,4]
  write(*,*) 5 .in. [1,2,3,4]
end program main
$ fpm run
 T
 F
  • 重载的函数和运算符不能用于Fortran的回调函数中。Fortran目前也没有lambda表达式。