fortran operator overloading (=)

匿名 (未验证) 提交于 2019-12-03 01:34:02

问题:

Is there a way to overload the = operator so that you can write an assignment like in this example:

  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 

I've tried two different ways (shown in comments) but I get errors saying that there is a syntax error in generic specification (for publicizing the = operator). Any help on doing this is greatly appreciated!

回答1:

For defined assignment operator(=) is not correct, but assignment(=) is: see Fortran 2008 12.4.3.4.3. So you instead want the two lumps

public :: assignment (=) 

and

interface assignment (=)   module procedure vectorAssign end interface 

Note that the correct way to define the assignment is by the subroutine as you have it (although the assignee could have intent(out) instead of intent(inout)).



回答2:

= is not an operator, it is an assignment in Fortran and they are very different beasts.

To the classical possibility found in Fortran 90 and explained well in other answers, Fortran 2003 added a better possibility to bind the overloaded operators and assignments with the derived type.

This way you are sure you will not import the type without the assignment (beware of public and private statement in this case!). It can have very unpleasant consequences and can be hard to debug:

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

This way you do not have to be that careful to not forget the public :: assignment (=)



回答3:

Yes, you can overload the assignment operator. The syntax and requirements are different for the assignment operator than for other operators because the semantics are fundamentally different: all other operators compute a new value based on one or two arguments, without changing the arguments, whereas assignment changes the value of the left-hand argument.

In your case, I think it should look like this:

module vectorField_mod  ! ...    interface assignment (=)     module procedure vectorAssign   end interface  contains    ! ...    subroutine vectorAssign(f,g)     implicit none     type(vectorField),intent(out) :: f     real(kind = dpn), intent(in) :: g     f%x = g     f%y = g     f%z = g   end subroutine vectorAssign  end module vectorField_mod 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!