- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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...
![](/skins/images/3CECF0550DB8BF54496C114A1FF06FE9/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page