Fortran subroutine left to user - fortran

I am trying in an object-oriented fashion to have a type that implements all functionalities, except for one function that should be implemented by the user.
Suppose I have two modules with types, an animal and a cat extending animal. Now I'd like to implement a way of passing a custom procedure to any animal. I don't know what is the best way of implementing such a feature. Right now I've succeeded in having all cat objects have a function caller that that will take a subroutine as an argument, but only if the type is explicit, or in other words, if the type is not an animal and at runtime I create a cat:
animal
module animal_module
implicit none
type, abstract :: animal
private
integer, public :: nlegs = -1
contains
procedure :: legs
procedure :: speak
end type animal
interface animal
module procedure init_animal
end interface animal
contains
type(animal) function init_animal(this)
class(animal), intent(inout) :: this
print *, "Animal!"
this%nlegs = -4
end function init_animal
function legs(this) result(n)
class(animal), intent(in) :: this
integer :: n
n = this%nlegs
end function legs
subroutine speak(this, ntimes)
class(animal), intent(in) :: this
integer, intent(in) :: ntimes
integer :: i
do i = 1, ntimes
print *, "generic animal :: speak"
end do
end subroutine speak
end module animal_module
cat
module cat_module
use animal_module, only : animal
implicit none
type, extends(animal) :: cat
private
real :: hidden = 23.
contains
! something like this? maybe a pointer?
procedure :: caller
procedure :: speak
end type cat
interface cat
module procedure init_cat
end interface cat
abstract interface
subroutine sub_interface
end subroutine
end interface
contains
type(cat) function init_cat()
print *, "Cat!"
init_cat%nlegs = 4
end function init_cat
subroutine caller(this, sub)
class(cat), intent(inout) :: this
procedure(sub_interface) :: sub
print *, "caller begin", this%nlegs
call sub()
print *, "caller ended", this%nlegs
end subroutine caller
subroutine speak(this, ntimes)
class(cat), intent(in) :: this
integer, intent(in) :: ntimes
integer :: i
do i = 1, ntimes
print *, "cat :: meow"
end do
end subroutine speak
end module cat_module
main program
subroutine ahoy
print *, "ahoy"
end subroutine ahoy
program oo
use animal_module
use cat_module
use bee_module
implicit none
class(animal), allocatable :: q
procedure(sub_interface) :: ahoy
class(cat), allocatable :: p
! THIS WON'T WORK
allocate(cat :: q)
q = cat()
call q%caller(ahoy)
! no problem with this
allocate(cat :: p)
p = cat()
call p%caller(ahoy)
end program
The error I am getting in calling caller from an animal is
/oo/main.F90(28): error #6460: This is not a field name that is defined in the encompassing structure. [CALLER]
call q%caller(ahoy)
-----------^
As far as I understand, this should normal: as animal has no clue a cat contains caller, it will not work. Am I right?
How can I let users implement a subroutine that will be called by a caller function? The called function should have access to the type, the user-provided function should be able to modify the hidden integer in a cat object.

Related

Best way to generate a variable type fortran array (each element can be a different type)

Following a previous question I had (Fortran TYPE inheritance on runtime (declared by user)), I am using a factory method to generate an array of different types. Below is a simplified version of what I'm doing,
module multiarray
use iso_fortran_env, only: real64
implicit none
integer, parameter :: dp = real64
! abstract list type
type, abstract :: list
contains
procedure(in), deferred, pass(self) :: addval ! add a variable
procedure(out), deferred, pass(self) :: getval ! extract variable
end type
abstract interface
subroutine in(self,val)
import :: list
implicit none
class(list), intent(inout) :: self
class(*), intent(in) :: val
end subroutine
subroutine out(self,val)
import :: list
implicit none
class(list), intent(in) :: self
class(*), intent(out) :: val
end subroutine
end interface
! real(dp) element extension
type, extends(list) :: real_num
real(dp) :: var
contains
procedure, pass(self) :: addval => addreal
procedure, pass(self) :: getval => getreal
end type
! similar for character, logical, etc types
...
! wrapper
type wrapper
class(list), ALLOCATABLE :: arg
end type
contains
! real(dp) subroutines
subroutine addreal(self,val)
implicit none
class(real_num), intent(inout) :: self
class(*), intent(in) :: val
select type(val)
type is (real(dp))
self%var = val
end select
end subroutine
subroutine getreal(self,val)
implicit none
class(real_num), intent(in) :: self
class(*), intent(out) :: val
select type(val)
type is (real(dp))
val = self%var
end select
end subroutine
! similar for character, logical, etc types
...
! factory method
function get_list(val) result(pt)
class(*), intent(in) :: val
class(list), allocatable :: pt
select type(val)
type is (real(dp))
allocate(real_num :: pt)
type is (character(*))
...
end select
end function
end module
I use the wrapper type to generate an allocatable array of type list
type(wrapper) :: A(5)
real(dp) :: x
A(1)%arg = get_list(90.d0) ! Set A(1) as type real
call A(1)%arg%addval(90.d0) ! A(1) is a real of value 90
call A(1)%arg%getval(x) ! set x = A(1) to use elsewhere
The variable var is defined as a generic class in the abstract interface, it can be of real, character, logical, etc type. I then use a select type construct to match the addval=>addreal subroutine argument since var is of type class(*) in the abstract interface.
Is there a way to define an interface inside the abstract interface (nested), in a way that I don't need to have the select type in addreal (since I already know it's input needs to be a real type)? Or is there a better way, simpler way, to achieve what I'm trying to do with the variable type array? Thanks!
I think you don't want to have both class(*) inputs and an abstract base class. I think you want to have either one:
a non-polymorphic container class that can contain any (class(*)) element types, for example, a key-value pair in a dictionary;
a polymorphic container class if a limited set of types should later have a shared API.
In your case it seems you want maximum flexibility, I would vote for having a unique container class and making usage of class(*), like in the following example I've just made up:
! FP 2022-07-25
module myList
use iso_fortran_env
implicit none
type, public :: listElement
class(*), allocatable :: x
contains
procedure :: set
procedure :: get_any
procedure :: get_typed
procedure, private :: print
generic :: write(formatted) => print
end type listElement
contains
! Map accepted types
elemental logical function isAccepted(val)
class(*), intent(in) :: val
select type (input=>val)
type is (real(real32)); isAccepted = .true.
type is (character(*)); isAccepted = .true.
class default; isAccepted = .false.
end select
end function isAccepted
! Print value
subroutine print(this, unit, iotype, v_list, iostat, iomsg)
class(listElement), intent(in) :: this
integer, intent(in) :: unit
character(*), intent(in) :: iotype
integer, intent(in) :: v_list(:)
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
if (.not.allocated(this%x)) then
write(unit,*,iostat=iostat) 'null'
else
select type (myVar => this%x)
type is (real(real32)); write(unit,*,iostat=iostat) myVar
type is (character(*)); write(unit,*,iostat=iostat) myVar
class default; write(unit,*,iostat=iostat) "ERROR"
end select
endif
end subroutine print
subroutine set(this,val)
class(listElement), intent(inout) :: this
class(*), intent(in) :: val
integer :: ierr
deallocate(this%x,stat=ierr) ! force deallocate
allocate(this%x,source=val)
end subroutine set
! Can be anything, but "val" must be declared "class(*), allocatable"
subroutine get_any(this,val)
class(listElement), intent(in) :: this
class(*), intent(out), allocatable :: val
allocate(val,source=this%x)
end subroutine get_any
subroutine get_typed(this,val)
class(listElement), intent(in) :: this
class(*), intent(out) :: val ! has a type that can't change
if (.not.isAccepted(val)) stop ' trying to return value to a class thats not supported '
if (.not.allocated(this%x)) return ! will return garbage
select type (outVal => val)
type is (real(real32));
select type (thisVal => this%x)
type is (real(real32)); outVal = thisVal
type is (real(real64)); outVal = real(thisVal,real32)
class default; stop 'error trying to convert list element to real32'
end select
type is (character(*));
select type (thisVal => this%x)
type is (character(*)); outVal = trim(thisVal)
class default; stop 'error trying to convert list element to character'
end select
class default
stop 'trying to return value to a class thats not accepted '
end select
end subroutine get_typed
end module myList
program tryList
use myList
implicit none
type(listElement) :: A(5)
integer :: i
character(255) myChar
real(real32) :: r32
real(real64) :: r64
call A(1)%set(123.45)
call A(2)%set("hello world!")
call A(3)%set(123.45d0)
do i=1,3
print *, 'A(',i,')=',A(i)
end do
call A(1)%get_typed(r64); print *, 'r64=',r64
call A(1)%get_typed(r32); print *, 'r32=',r32
call A(2)%get_typed(myChar); print *, 'myChar=',myChar
call A(2)%get_typed(r32) ! stop on error
end program
Notice that:
In general, this should work with any variables (class(*)), but if you want to use the fully polymorphic interface, the input variable must be defined as class(*), allocatable anywhere else, so, not exactly handy.
You want to have some helper routines and/or an enumerator type that help you map/handle all types you want to be contained, this example is just a stub.

Nopass procedure pointer passed between derived types causes Segmentation fault

I want to pass a procedure pointer between two classes in modern Fortran.
this procedure pointer should
be called from within the second object
access the first ojects' components, without having it as dummy argument.
A clear example is here, imagine doing an object-oriented wrapper of an ODE solver:
module test_funptr
implicit none
public
type, public :: ode_solver
integer :: NEQ = 0
procedure(ode_api), pointer, nopass :: f => null()
contains
procedure :: run
end type ode_solver
type, public :: ode_problem
integer :: NEQ = 10
procedure(ode_api), pointer, nopass :: yprime => null()
contains
procedure :: init
end type ode_problem
abstract interface
subroutine ode_api(NEQ,YDOT)
integer, intent(in) :: NEQ
real(8), intent(inout) :: YDOT(NEQ)
end subroutine ode_api
end interface
contains
! Initialize problem variables
subroutine init(this,NEQ)
class(ode_problem), intent(inout) :: this
integer, intent(in) :: NEQ
! Associate function pointer
this%yprime => problem_api
contains
! nopass ODE solver API
subroutine problem_api(NEQ,YDOT)
integer, intent(in) :: NEQ
real(8), intent(inout) :: YDOT(NEQ)
integer :: i
print *, 'entered problem API with NEQ=',NEQ
forall(i=1:NEQ) YDOT(i) = real(i,8)
end subroutine
end subroutine init
subroutine run(this)
class(ode_solver), intent(inout) :: this
real(8) :: ydot(this%neq)
ydot = 0.0
print *, 'enter solver run with NEQ=',this%NEQ
print *, 'is function associated? ',associated(this%f)
call this%f(this%neq,ydot)
end subroutine run
end module test_funptr
program test
use test_funptr
type(ode_solver) :: solver
type(ode_problem) :: prob
call prob%init(10)
! Associate ode solver
solver%neq = prob%NEQ
solver%f => prob%yprime
call solver%run()
end program test
This program returns with gfortran-10:
enter solver run with NEQ= 10
is function associated? T
Program received signal SIGILL: Illegal instruction.
The procedure seems properly associated, but it can't be called. Am I doing something wrong passing the procedure pointers, or I'm doing something out-of-standard? I'm concerned the contained subroutine may go out of scope, but if so, how can I achieve this behavior?
The tricky part is of course that the function should access data from the other variable instance.
It is illegal to invoke a procedure pointer to an internal procedure, after the host procedure gets out of scope.
The draft of Fortran 2015 N2123 mentions this in NOTE 15.17
NOTE 15.17
An internal procedure cannot be invoked using a procedure
pointer from either Fortran or C after the host instance completes
execution, because the pointer is then undefined. While the host
instance is active, however, if an internal procedure was passed as an
actual argument or is the target of a procedure pointer, it could be
invoked from outside of the host subprogram.
... an example follows
Often, internal procedures are implemented using trampolines. That is, a piece of executable code placed on the stack, that enables accessing the local scope and calls the procedure itself. The pointer is then a pointer to the trampoline. Once the host function gets out of scope, the pointer to the stack is invalid.
As pointed out, internal (contained) procedures are not the way to go, as they cannot be targets to procedure pointers. Hopefully this will be catched by the compilers.
I've figured out an elegant way to accomplish the aim to pass an interfaced procedure between two classes this way:
class 1 needs to call that function: it must contain a pointer to class 2
The nopass function should be inside this class, as an internal procedure (this way, it'll never go out of scope)
This class must contain a (polymorphic) pointer to the instantiated object from class 2
class 2 contains the actual implementation, it should instantiate an abstract type that contains the same interfaced function, but with the derived type as dummy argument
Here I'm providing an implementation that works:
module odes
implicit none
type, abstract, public :: ode_problem
integer :: NEQ
contains
procedure(ode_api), deferred :: fun
end type ode_problem
type, public :: ode_solver
integer :: NEQ
class(ode_problem), pointer :: problem => null()
contains
procedure :: init
procedure :: run
end type ode_solver
abstract interface
subroutine ode_api(this,YDOT)
import ode_problem
class(ode_problem), intent(inout) :: this
real(8), intent(out) :: YDOT(this%NEQ)
end subroutine ode_api
end interface
contains
! Associate problem to ODE solver
subroutine init(this,my_problem)
class(ode_solver), intent(inout) :: this
class(ode_problem), intent(in), target :: my_problem
this%neq = my_problem%NEQ
this%problem => my_problem
end subroutine init
! call the nopass f77 interface function
subroutine run(this)
class(ode_solver), intent(inout) :: this
real(8) :: YDOT(this%NEQ)
integer :: i
if (.not.associated(this%problem)) stop 'solver not associated to a problem'
! This will be in general passed to another function as an argument
call ode_f77_api(this%NEQ,YDOT)
contains
subroutine ode_f77_api(NEQ,YDOT)
integer, intent(in) :: NEQ
real(8), intent(out) :: YDOT(NEQ)
! This is just a nopass interface to this problem's function that can
! access internal storage
call this%problem%fun(YDOT)
end subroutine ode_f77_api
end subroutine run
end module odes
! Provide an actual implementation
module my_ode_problem
use odes
implicit none
type, public, extends(ode_problem) :: exp_kinetics
real(8) :: k = -0.5d0
contains
procedure :: fun => exp_fun
end type exp_kinetics
contains
subroutine exp_fun(this,YDOT)
class(exp_kinetics), intent(inout) :: this
real(8), intent(out) :: YDOT(this%NEQ)
integer :: i
forall(I=1:this%NEQ) YDOT(i) = this%k*real(i,8)
print 1, this%NEQ,(i,YDOT(i),i=1,this%NEQ)
1 format('test fun! N=',i0,': ',*(/,10x,' ydot(',i0,')=',f5.2,:))
end subroutine exp_fun
end module my_ode_problem
program test_fun_nopass
use odes
use my_ode_problem
implicit none
type(exp_kinetics) :: prob
type(ode_solver) :: ode
prob%NEQ = 10
call ode%init(prob)
call ode%run()
stop 'success!'
end program test_fun_nopass
This program returns:
test fun! N=10:
ydot(1)=-0.50
ydot(2)=-1.00
ydot(3)=-1.50
ydot(4)=-2.00
ydot(5)=-2.50
ydot(6)=-3.00
ydot(7)=-3.50
ydot(8)=-4.00
ydot(9)=-4.50
ydot(10)=-5.00
STOP success!

Function of array of pointers to abstract class returning an array

I'd like to create a generic integration library for my project, which would operate on different functions, with different integration methods. The idea is that I can call
next_step(:) = my_integration_function(previous_step, dt, args)
Here next_step is simply an array of coefficient (typically of type real64), while previous_step is an array of objects corresponding to functions at different time step, with their parameters (used to compute derivatives for instance). So I need functions that operate on arrays of abstract classes, that can return arrays of real with a dimension depending on the function integrated, typically the first element of previous_step.
My problem is that I have a compiler segfault when I try to compile the following code with gfortran 10.3 (Opensuse):
module baseClass
implicit none
type, abstract, public :: base
integer, allocatable :: i(:)
contains
procedure(sub), deferred, pass :: mysub
end type base
abstract interface
subroutine sub(bb)
import :: base
class(base), intent(in) :: bb
end subroutine sub
end interface
type, public :: baseWrap
class(base), pointer :: p
end type baseWrap
public :: operate_on_baseWrap
contains
function operate_on_baseWrap(wrapped) result(res)
class(baseWrap), intent(in) :: wrapped(:)
integer :: i, tmp
integer, dimension(size(wrapped(1)%p%i)) :: res
do i=1, size(wrapped)
call wrapped(i)%p%mysub
end do
res = 0
end function operate_on_baseWrap
end module baseClass
module childClass
use baseClass
implicit none
type, extends(base), public :: child1
contains
procedure, pass :: mysub => sub_child1
end type child1
contains
subroutine sub_child1(bb)
class(child1), intent(in) :: bb
print *, 'Do something', bb%i
end subroutine sub_child1
end module childClass
program test
use baseClass
use childClass
implicit none
type(baseWrap), allocatable :: wrapper(:)
type(child1), allocatable, target :: c(:)
integer :: i
integer, allocatable :: tmp(:)
allocate(wrapper(3))
allocate(c(3))
do i=1, 3
allocate(c(i)%i(3))
c(i)%i = i
wrapper(i)%p => c(i)
end do
allocate(tmp(size(wrapper(1)%p%i)))
tmp = operate_on_baseWrap(wrapper)
end program test
Here is the compiler error:
baseClass.f90:139:36:
139 | tmp = operate_on_baseWrap(wrapper)
| 1
internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <https://bugs.opensuse.org/> for instructions.
Here baseClass would be the general integration library, and child1 could be a specific function which I want to integrate.
The problem seems to come from operate_on_baseWrap returning an array, with a size given by one of the element of wrapped array.
Is it forbidden by the standard, or is it a compiler bug ?
Thanks for your insight !

Type bound procedure as arguments

I want to pass a type bound procedures (as an external function) to another function as follows:
module mod1
implicit none
type type1
real :: a
contains
procedure,pass :: f
end type
contains
real function f(y,e)
class(type1), intent(in) :: y
real,intent(in) :: e
f=y%a+e
end function
end module
program test
use mod1
type(type1) :: t
t%a=3e0
write(*,*) s(t%f)
contains
real function s(g)
real,external :: g
s=g(5e0)+2e0
end function
end program
gfortran produces gives this error :
write(*,*) s(t%f)
1
Error: Expected argument list at (1)
But what I can do is:
program test
t%a=3e0
write(*,*) s(k)
contains
real function s(g)
real,external :: g
s=g(5e0)+2e0
end function
real function k(e)
real,intent(in) :: e
k=3e0+e
end function
end program
I think the problem is related to Passing type bound procedures as arguments, but I don't see at the moment how the answers there can help me.
EDIT:
A better example which (hopefully) shows the difficulty:
module mod2
implicit none
contains
real function s(g)
interface
real function g(x)
real, intent(in) :: x
end function
end interface
s=g(5e0)+2e0
end function
end module
module mod1
use mod2
type type1
real :: a
contains
procedure,pass :: f
procedure,pass :: h
end type
contains
real function f(y,e)
class(type1), intent(in) :: y
real,intent(in) :: e
f=y%a+e
end function
real function h(y)
class(type1), intent(inout) :: y
h=s(y%f)
end function
end module
program test
use mod1
type(type1) :: t
t%a=3e0
write(*,*) t%h
end program
EDIT II:
Ok, the wrappers still work in combination with a pointer:
module mod2
implicit none
contains
real function s(g)
interface
real function g(x)
real, intent(in) :: x
end function
end interface
s=g(5e0)+2e0
end function
end module
module mod1
use mod2
type type1
real :: a
contains
procedure,pass :: f
procedure,pass :: h
end type
class(type1),pointer :: help_w
contains
real function f(y,e)
class(type1), intent(in) :: y
real,intent(in) :: e
f=y%a+e
end function
real function h(y)
class(type1), intent(inout),target :: y
help_w => y
h=s(wrap)
end function
function wrap(x)
real,intent(in) :: x
wrap=help_w%f(x)
end function
end module
program test
use mod1
type(type1) :: t
t%a=3e0
write(*,*) t%h()
end program
This is certainly not a beautiful solution but at least it works.
You can write a wrapper. This is the most straightforward version. Requires passing internal function as a dummy argument (F2008), but you could declare the wrapper in a module too, if the t can bee there.
Note I changed the declaration of the procedure argument in s to something more modern - the interface block.
program test
use mod1
type(type1) :: t
t%a=3e0
write(*,*) s(wrap)
contains
real function s(g)
interface
real function g(x)
real, intent(in) :: x
end function
end interface
s=g(5e0)+2e0
end function
function wrap(x)
real, intent(in) :: x
wrap = t%f(x)
end function
end program
The reason for your error is well described in the answers to the linked question, you cannot pass type bound procedures the way you tried.

Store a "pointer to function" in Fortran?

In Fortran, you can pass a function/subroutine A as an argument to another function/subroutine B, but can you store A for later retrieval and use?
for example, this is allowed in C
int foo(float, char, char) { /*whatever*/};
int (*pointerToFunction)(float, char, char);
pointerToFunction = foo;
In Fortran you can pass a subroutine as an argument
subroutine foo
! whatever
end subroutine foo
subroutine bar(func)
call func
end subroutine bar
program x
call bar(foo)
end program
but how can you store the address of foo in a similar way to C ?
Starting from so-called "Fortran 2003" (ISO/IEC 1539-2004) procedure pointers is a part of the Fortran language. It's definitely of the major new features of Fortran language.
Usage example from Fortran Wiki.
Stefano, you mentioned strategy design pattern. In Fortran 2003 you can use pure OOP way to implement it (without procedure pointers). Offhand example:
strategies.f90
module strategies
implicit none
private
public :: strategies_transportation_strategy, &
strategies_by_taxi_strategy, &
strategies_by_bus_strategy
type, abstract :: strategies_transportation_strategy
contains
procedure(transportation_strategy_go), deferred :: go
end type strategies_transportation_strategy
type, extends(strategies_transportation_strategy) :: strategies_by_taxi_strategy
contains
procedure :: go => strategies_by_taxi_strategy_go
end type strategies_by_taxi_strategy
type, extends(strategies_transportation_strategy) :: strategies_by_bus_strategy
contains
procedure :: go => strategies_by_bus_strategy_go
end type strategies_by_bus_strategy
abstract interface
subroutine transportation_strategy_go(this)
import strategies_transportation_strategy
class(strategies_transportation_strategy), intent(in) :: this
end subroutine transportation_strategy_go
end interface
contains
subroutine strategies_by_taxi_strategy_go(this)
class(strategies_by_taxi_strategy), intent(in) :: this
print *, "We are using taxi."
end subroutine strategies_by_taxi_strategy_go
subroutine strategies_by_bus_strategy_go(this)
class(strategies_by_bus_strategy), intent(in) :: this
print *, "We are using public transport."
end subroutine strategies_by_bus_strategy_go
end module strategies
vehicles.f90
module vehicles
use strategies
implicit none
private
public :: vehicles_vehicle, &
vehicles_taxi, &
vehicles_bus
type, abstract :: vehicles_vehicle
private
class(strategies_transportation_strategy), allocatable :: transportation_strategy
contains
procedure :: set_transportation_strategy => vehicle_set_transportation_strategy
procedure :: go => vehicle_go
end type vehicles_vehicle
type, extends(vehicles_vehicle) :: vehicles_taxi
contains
procedure :: init => taxi_init
end type vehicles_taxi
type, extends(vehicles_vehicle) :: vehicles_bus
contains
procedure :: init => bus_init
end type vehicles_bus
contains
subroutine vehicle_go(this)
class(vehicles_vehicle), intent(in) :: this
call this%transportation_strategy%go()
end subroutine vehicle_go
subroutine vehicle_set_transportation_strategy(this, new_transportation_strategy)
class(vehicles_vehicle), intent(inout) :: this
class(strategies_transportation_strategy), intent(in) :: new_transportation_strategy
if (allocated(this%transportation_strategy)) then
deallocate (this%transportation_strategy)
end if
allocate (this%transportation_strategy, source=new_transportation_strategy)
end subroutine vehicle_set_transportation_strategy
subroutine taxi_init(this)
class(vehicles_taxi), intent(out) :: this
type(strategies_by_taxi_strategy) :: by_taxi_strategy
call this%set_transportation_strategy(by_taxi_strategy)
end subroutine taxi_init
subroutine bus_init(this)
class(vehicles_bus), intent(out) :: this
type(strategies_by_bus_strategy) :: by_bus_strategy
call this%set_transportation_strategy(by_bus_strategy)
end subroutine bus_init
end module vehicles
main.f90
program main
use vehicles
implicit none
type(vehicles_taxi) :: taxi
type(vehicles_bus) :: bus
call taxi%init()
call bus%init()
call taxi%go()
call bus%go()
end program main
At least works using gfortran 4.6 (20100925).
The following codes demonstrate how to use procedure pointers:
module my_mod
implicit none
contains
subroutine sub1()
write(*,*) 'the first suboutine is being used'
end subroutine sub1
subroutine sub2()
write(*,*) 'the second subroutine is being used'
end subroutine sub2
end module my_mod
program procTest
use my_mod
implicit none
integer :: n
procedure(sub1), pointer:: funPointer => NULL()
write(*,'(A)') "Please enter your option"
read(*,*) n
select case( n )
case( 1 )
funPointer => sub1
case( 2 )
funPointer => sub2
case DEFAULT
funPointer => sub1
end select
call funPointer()
end program procTest