Search code examples
fortran

Procedure pointer vs procedure name as argument of Fortran procedures


My understanding is that we can pass the information about which procedure should be used inside a Fortran procedure, either using an argument and declaring it to be a procedure name through a specific interface, or using an argument declared to be a procedure pointer.

I do not think I have grasped all pros and cons of the two alternatives. Maybe one has some limitations not present with the other? Are there efficiency issues?


Just to make clear what this question is about (if necessary), I'll briefly recall through two examples the different ways of passing information about which procedure should be used inside a procedure, through the procedure arguments.

  1. using an argument and declaring it to be a procedure name through a specific interface
module pro
 implicit none
contains

 function myfunction(x) result(res) ! this is an actual function with the right signature to be used as argument of the subroutine prosub
    real, intent(in) :: x
    real :: res
    res = 2*x
 end function myfunction

 subroutine prosub(f,x)
   real, intent(in) :: x
   procedure(myfunction) :: f  ! the actual argument used in place of the dummy argument f must be the name of a function with the same signature as myfunction
   print*,f(x)
 end subroutine prosub
end module pro

program ppp
 use pro
 implicit none
 real :: x
 print*,' x= ?'
 read*,x
 call prosub(myfunction,x)
end program ppp

  1. using an argument declared to be a procedure pointer
module pro
 implicit none
 abstract interface ! defines the signature of the functions the procedure pointers argument of the subroutine prosub must have
   function f(x) result(res)
     real, intent(in) :: x
     real :: res
   end function f
 end interface

contains

 function myfunction(x) result(res) ! one of the possible actual functions the procedure pointer can point to
    real, intent(in) :: x
    real :: res
    res = 2*x
 end function myfunction

 subroutine prosub(fp,x)
   real, intent(in) :: x
   procedure(f), pointer :: fp
   print*,fp(x)
 end subroutine prosub
end module pro

program ppp
 use pro
 implicit none
 real :: x
 procedure(f), pointer :: f1

 f1 => myfunction

 print*,' x= ?'
 read*,x
 call prosub(f1,x)
end program ppp 


Solution

  • A dummy procedure pointer, when contrasted with a non-pointer dummy procedure, may (depending on argument intent and the like):

    1. be passed in as disasssociated or undefined,
    2. have its association status tested,
    3. have its association status changed,
    4. pass out information to the calling context.

    If these capabilities are useful to have when writing a subprogram, then there might be a need for a dummy procedure pointer.

    Specifying that something is a procedure pointer or non-pointer is orthogonal to how you specify the interface. There is no semantic difference between a declaration of the form

    procedure(some_interface) :: proc
    

    and writing out an interface body for proc that has the same characteristics as some_interface. In your first "non-pointer" program, you could have equally written:

    subroutine prosub(f,x)
      real, intent(in) :: x
      procedure(myfunction) :: f  ! or use the abstract interface
      print*,f(x)
    end subroutine prosub
    

    and in your second "pointer" program, you could have written:

    subroutine prosub(fp,x)
      real, intent(in) :: x
     
      interface 
        function fp(x) result(res)
          real, intent(in) :: x
          real :: res
        end function fp
      end interface
      pointer :: fp
     
      print*,fp(x)
    end subroutine prosub
    

    This choice comes down to whether you want to specify the (perhaps abstract) interface in one location, or how much you like typing.