Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a generic procedure to a function as actual argument

Tags:

fortran

I am attempting to pass a generic procedure as an actual argument to a function:

module mymod
implicit none

interface func
  module procedure :: func1
  module procedure :: func2
endinterface func

contains

real function func1(x)
  real,intent(in) :: x
  func1 = 2*x
endfunction func1

real function func2(x,y)
  real,intent(in) :: x
  real,intent(in) :: y
  func2 = 2*x + 3*y
endfunction func2

real function func3(func,x,y)
  interface
    real function func(x,y)
      real,intent(in) :: x
      real,intent(in) :: y
    endfunction func
  endinterface
  real,intent(in) :: x
  real,intent(in) :: y
  func3 = func(x,y)
endfunction func3

endmodule mymod

program myprogram
use mymod
implicit none
write(*,*)func3(func,2.,3.)
endprogram myprogram

gfortran 6.2.0 notes that I cannot do this:

test.f90:43:16:

 write(*,*)func3(func,2.,3.)
                1
Error: GENERIC procedure ‘func’ is not allowed as an actual argument at (1)

Similarly, with ifort 17:

test.f90(39): error #8164: A generic interface name shall not be used as an actual argument.   [FUNC]
write(*,*)func3(func,2.,3.)
----------------^
test.f90(39): error #6637: When a dummy argument is a function, the corresponding actual argument must also be a function.   [FUNC]
write(*,*)func3(func,2.,3.)
----------------^
compilation aborted for test.f90 (code 1)

I am reading through the 2008 Standard section on generic interfaces and I cannot find such restriction. I also cannot think of a reason why the compiler would not be able to resolve the generic interface at compile-time. My gut is telling me that this should be doable, but I may not have the right approach. Do you know of a standard-compliant way to do this?

like image 382
milancurcic Avatar asked Sep 22 '16 16:09

milancurcic


1 Answers

No, this is not allowed. Actually, you cannot even pass generic INTRINSIC functions as dummy arguments.

A standard compliant way is to use the right specific functions directly. With INTRINSIC functions you sometimes must write a wrapper for the right kind, when the specific doesn't have a standard name.

For example:

  call integrate(derf,0.,1.)

  contains
    function derf(x)
      real(dbl) :: derf
      real(dbl), intent(in) :: x
      derf = erf(x)
    end function
  end

is necessary if you want to pass the double precision real (or any other) version of erf() because there is no specific function available.

like image 131
Vladimir F Героям слава Avatar answered Sep 25 '22 18:09

Vladimir F Героям слава