fortran运算符重载(=)

Cha*_*les 3 oop fortran operator-overloading gfortran

有没有办法重载=运算符,以便您可以编写如下示例中的赋值:

  module constants_mod
    integer,parameter :: dpn = selected_real_kind(14)
  end module

  module vectorField_mod
    use constants_mod
    implicit none
    private

    public :: vectorField
    public :: allocateX,allocateY,allocateZ
    public :: delete
    ! public :: operator(=)

    type vectorField
      integer,dimension(3) :: sx,sy,sz
      real(dpn),dimension(:,:,:),allocatable :: x,y,z
    end type

  interface delete
    module procedure deallocateVectorField
  end interface

  ! interface operator (=)
  !   module procedure vectorAssign
  ! end interface

  contains

    ! function vectorAssign(f) result(q)
    !   implicit none
    !   real(dpn),intent(in) :: f
    !   type(vectorField) :: q
    !   q%x = f; q%y = f; q%z = f
    ! end function

    ! subroutine vectorAssign(f,g)
    !   implicit none
    !   type(vectorField),intent(inout) :: f
    !   real(dpn),intent(in) :: g
    !   f%x = g; f%y = g; f%z = g
    ! end subroutine

    subroutine allocateX(field,Nx,Ny,Nz)
      implicit none
      type(vectorField),intent(inout) :: field
      integer,intent(in) :: Nx,Ny,Nz
      if (allocated(field%x)) deallocate(field%x)
      allocate(field%x(Nx,Ny,Nz))
      field%sx = shape(field%x)
    end subroutine

    subroutine allocateY(field,Nx,Ny,Nz)
      implicit none
      type(vectorField),intent(inout) :: field
      integer,intent(in) :: Nx,Ny,Nz
      if (allocated(field%y)) deallocate(field%y)
      allocate(field%y(Nx,Ny,Nz))
      field%sy = shape(field%y)
    end subroutine

    subroutine allocateZ(field,Nx,Ny,Nz)
      implicit none
      type(vectorField),intent(inout) :: field
      integer,intent(in) :: Nx,Ny,Nz
      if (allocated(field%z)) deallocate(field%z)
      allocate(field%z(Nx,Ny,Nz))
      field%sz = shape(field%z)
    end subroutine

    subroutine deallocateVectorField(field)
      implicit none
      type(vectorField),intent(inout) :: field
      deallocate(field%x,field%y,field%z)
      field%sx = 0; field%sy = 0; field%sz = 0
    end subroutine

  end module

  program test
  use constants_mod
  use vectorField_mod
  implicit none
  type(vectorField) :: a
  integer :: N = 1
  real(dpn) :: dt = 0.1
  call allocateX(a,N,N,N)
  call allocateY(a,N,N,N)
  call allocateZ(a,N,N,N)

  a%x = dble(1.0) ! want to avoid this
  a%y = dble(1.0) ! want to avoid this
  a%z = dble(1.0) ! want to avoid this

  a = real(1.0,dpn) ! want this instead (does not compile)

  call delete(a)

  end program
Run Code Online (Sandbox Code Playgroud)

我尝试了两种不同的方式(在注释中显示)但我得到错误,说通用规范中存在语法错误(用于公开=运算符).任何帮助这样做非常感谢!

Vla*_*r F 6

= 它不是运算符,它是Fortran中的一个赋值,它们是非常不同的动物.

对于在Fortran 90中发现的经典可能性以及在其他答案中得到很好解释,Fortran 2003添加了更好的可能性来将重载的运算符和赋值与派生类型绑定.

这样您就可以确保在没有赋值的情况下不会导入类型(在这种情况下要注意公共和私有语句!).它可能会产生非常不愉快的后果,并且很难调试:

type vectorField
  integer,dimension(3) :: sx,sy,sz
  real(dpn),dimension(:,:,:),allocatable :: x,y,z
contains
  procedure :: assignVector
  generic :: assignment(=) => assignVector
end type
Run Code Online (Sandbox Code Playgroud)

这样你就不必小心不要忘记了 public :: assignment (=)


fra*_*lus 5

对于定义的赋值operator(=)不正确,而是assignment(=):参见 F​​ortran 2008 12.4.3.4.3。所以你想要两个肿块

public :: assignment (=)
Run Code Online (Sandbox Code Playgroud)

interface assignment (=)
  module procedure vectorAssign
end interface
Run Code Online (Sandbox Code Playgroud)

请注意,定义分配的正确方法是通过您拥有的子例程(尽管受让人可以用intent(out)代替intent(inout))。

  • 这可以追溯到 Fortran 90。 (2认同)