Runtime determination of procedure pointer name.

Runtime determination of procedure pointer name.

I confess I did not study at length the subject, but it seems that what I want here is not possible.

I wrote a module with a set of procedures all with the same abstract interface.  The procedure is to be chosen at runtime using a procedure pointer.  However, I want the actual name of the procedure to be given by the user.

The following code shows a naive (and wrong) attempt:

---------------------------------------------------------------------------------

module temp
implicit none
abstract interface
   function f(x)
   real, intent(in) :: x
   real             :: f
   end function f
end interface
procedure(f), pointer :: p => null()
CONTAINS
   function f1(x)
   real, intent(in) :: x
   real             :: f1
   f1= x*x
   return
   end function f1
!***
   function f2(x)
   real, intent(in) :: x
   real             :: f2
   f2= sqrt(x)
   return
   end function f2
end module temp
program tes_procedure_pointer
use temp
implicit none
real :: x
character(len= 2), target :: fun
write(*, '(a)')'Choose function:'
write(*, '(a)')'f1: x^2'
write(*, '(a)')'f2: sqrt(x)'
write(*, '(a)', advance='no')'Option (f1/f2): '
read(*,'(a)')fun
select case (fun)
case('f1')
   p => fun
case('f2')
   p => fun
end select
do
   write(*,fmt='("x= ")',advance='no')
   read(*,*) x
   print*, 'The output is:'
   write(*,*) p(x)
   write(*,*) ' '
end do
end program tes_procedure_pointer

-------------------------------------------------------------------------

The compiler gives the following error message:

tes_proc_pointer2.f90(38): error #8191: The procedure target must be a procedure or a procedure pointer.   [FUN]
   p => fun
--------^
tes_proc_pointer2.f90(40): error #8191: The procedure target must be a procedure or a procedure pointer.   [FUN]
   p => fun
--------^

Is there a way to implement this? Or is it not permitted?

Thanks

 

publicaciones de 4 / 0 nuevos
Último envío
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.

well the easy way to do this is:

 

select case (fun)
case('f1')
   p => f1
case('f2')
   p => f2
end select

it's not elegant as the function target names are hardcoded.  Might be hard to maintain.  I'm sure there is a more clever way to do this, but this simple solution occurred to me first.

 

ron

A better way is to encapsulate the function selection in the module along with the function definitions.  this way you don't have to hard-code the function names all over your main program and procedures - do the case in 1 module subroutine.  Below is an example.  In practice, I would probably add the writes and read from the user in this subroutine select_p. 

module temp
implicit none
abstract interface
   function f(x)
   real, intent(in) :: x
   real             :: f
   end function f
end interface
procedure(f), pointer :: p => null()
CONTAINS
   function f1(x)
   real, intent(in) :: x
   real             :: f1
   f1= x*x
   return
   end function f1
!***
   function f2(x)
   real, intent(in) :: x
   real             :: f2
   f2= sqrt(x)
   return
   end function f2

   subroutine select_p( p_name, fptr )
     character(len=*), intent(in) :: p_name
     procedure(f), pointer :: fptr
     select case (p_name)
     case('f1')
       fptr => f1
     case('f2')
       fptr => f2
     case default
       write(*,*) "bad user input: ", p_name
       stop
     end select
 
   end subroutine select_p

end module temp
program tes_procedure_pointer
use temp
implicit none
real :: x
character(len= 2), target :: fun
write(*, '(a)')'Choose function:'
write(*, '(a)')'f1: x^2'
write(*, '(a)')'f2: sqrt(x)'
write(*, '(a)', advance='no')'Option (f1/f2): '
read(*,'(a)')fun
call select_p( fun, p )
do
   write(*,fmt='("x= ")',advance='no')
   read(*,*) x
   print*, 'The output is:'
   write(*,*) p(x)
   write(*,*) ' '
end do
end program tes_procedure_pointer

 

Yes, I was also thinking on a solution very similar to your select_p sub.

It's not what I wanted at first, but I guess it's the only solution, at least based on what I know about OOP (which is not much...). Besides, it's the only way whereby the executable can check whether the chosen routine exists.

I guess what I wanted (if possible at all) implies a heavy use of polymorphism, since I'd have to morph the character variable fun into a pointer procedure name.

I've found several sophisticated examples over the net that implemented polymorphism using type-bound procedure pointers and classes, but none seemed to really solve my problem.  Perhaps because it simply does not conform the standard, since the compiler wouldn't be able to check on the interface of the routine selected by the user.

Anyway, thanks a lot for the reply.  Please let me know if any other solution comes to mind...

Deje un comentario

Por favor inicie sesión para agregar un comentario. ¿No es socio? Únase ya