-
Notifications
You must be signed in to change notification settings - Fork 20
Open
Description
I thought the following type of pattern was allowed:
module action_dict_mod
implicit none
abstract interface
subroutine doit_fn()
end subroutine
end interface
type :: action
character(len=:), allocatable :: key
procedure(doit_fn), pointer, nopass :: doit => null()
end type
type :: action_dict
integer :: n = 0, capacity = 0
type(action), allocatable :: v(:)
contains
procedure :: set => set_action
procedure :: get => get_action
end type
contains
function set_action(dict,key) result(p)
class(action_dict), intent(inout), target :: dict
character(len=*), intent(in) :: key
procedure(doit_fn), pointer :: p
! Initialization and resizing logic
if (.not. allocated(dict%v)) then
dict%capacity = 10
allocate(dict%v(dict%capacity))
else if (dict%n >= dict%capacity) then
! Simple doubling of capacity if full
block
type(action), allocatable :: temp(:)
associate(new_capacity => dict%capacity * 2)
allocate(temp(new_capacity))
temp(1:dict%n) = dict%v
call move_alloc(temp, dict%v)
dict%capacity = new_capacity
end associate
end block
end if
! Add new entry
dict%n = dict%n + 1
dict%v(dict%n)%key = trim(key)
! Return the pointer to the procedure inside the dictionary
p => dict%v(dict%n)%doit
end function
function get_action(dict,key) result(p)
class(action_dict), intent(in) :: dict
character(len=*), intent(in) :: key
procedure(doit_fn), pointer :: p
integer :: i
p => null()
! Naive linear search
do i = 1, dict%n
if (dict%v(i)%key == trim(key)) then
p => dict%v(i)%doit
return
end if
end do
end function
end module
program main
use action_dict_mod
implicit none
type(action_dict) :: my_actions
procedure(doit_fn), pointer :: proc_ptr
! Using the F2008 pointer-function result to assign the procedure
my_actions%set("hello") => hello_sub
! Retrieve and execute
proc_ptr => my_actions%get("hello")
if (associated(proc_ptr)) call proc_ptr()
contains
subroutine hello_sub()
print *, "Hello, World!"
end subroutine
end program mainIt seems like there is a restriction on this. The Intel Fortran documentation says under "Disallowed Contexts":
For the following variable-definition contexts, the Fortran Standard specifies that a "variable name" must be used and not a "variable":
- [...]
- A data pointer object or procedure pointer object in a pointer assignment statement
This appears related to (J3/24-007, 10.2.2.2):
R1034 pointer-assignment-stmt is ...
or proc-pointer-object => proc-target
R1039 proc-pointer-object is proc-pointer-name
or proc-component-ref
R1040 proc-component-ref is scalar-variable % procedure-component-name
Is there any reason why an expr could not be added to R1039? The constraints on expr would be the same as,
C1032 (R1041) An expr shall be a reference to a function whose result is a procedure pointer.
The design is still achievable today, by using a wrapper type for the procedure pointer, effectively changing the pointer assignment into a data-pointer assigment.
As an implementation-note, this usage pattern also benefits from the extension proposed in #354.
Metadata
Metadata
Assignees
Labels
No labels