I'm in the following situation: I have an object that must be initialized (without hurry) with some input parameter x
. Then it has a method do_work
that has to run (fast). Now, depending on x
the do_work
can be either function f1
or f2
. Of course I can choose among them when do_work
is called, but, since I know the choice in advance, I was thinking to use a procedure pointer.
I produced the following MWE
module delegate_m
implicit none
private
type delegate
private
integer :: x
procedure(delegate_function), private, pointer :: fptr
contains
private
procedure:: f2
procedure :: f1
procedure, public :: do_work
end type delegate
interface delegate
module procedure :: init_delegate
end interface delegate
abstract interface
integer function delegate_function(self,y)
import :: delegate
class(delegate) :: self
integer :: y
end function delegate_function
end interface
public :: delegate
contains
type(delegate) function init_delegate(x)
implicit none
integer, intent(in) :: x
init_delegate%x = x
if (modulo(x, 2) == 0) then
init_delegate%fptr => f1
else
init_delegate%fptr => f2
end if
end function init_delegate
integer function f1(self,y)
implicit none
class(delegate) :: self
integer :: y
f1 = y * self%x
end function f1
integer function f2(self,y)
implicit none
class(delegate) :: self
integer :: y
f2 = (y ** 2) * self%x
end function f2
integer function do_work(self, x, y)
implicit none
class(delegate) :: self
integer:: x, y
do_work = self%fptr(x) - y
end function do_work
end module delegate_m
program test
use delegate_m
implicit none
type(delegate) :: d1, d2
d1 = delegate(45)
d2 = delegate(44)
write (*,*) d1%do_work(2, 3)
write (*,*) d2%do_work(2, 3)
end program test
It seems to work, but I'm rather new to (modern) Fortran and I would like to know whether I did something wrong/dangerous since I'm working with pointers. I'm also curios if that abstract interface
introduces some virtual function table lookup (I do not see why it should, but I'm a newbie, as I said)
CodePudding user response:
To answer your questions in order:
- It doesn't look like you've done anything dangerous or wrong. This looks to me like a good use case for procedure pointers, and your implementation looks good.
- The
abstract interface
is basically just defining the "type signature" of the procedure pointer. It doesn't add any overhead. - You will (unless it's somehow optimised out) have the overhead of a single pointer lookup every time you call
fptr
. This might or might not interfere with some possible compiler optimisations. It's really hard to say whether this will actually meaningfully slow anything down without just trying it to see, and running a code profiler to find out.