Встала задача такой организации вычислений, когда вызов необходимой процедуры следует осуществлять по индексу.
Фактически — необходимо создать массив указателей на процедуры.
В Фортране это затруднено тем, что описание вроде
real, pointer, dimension(:) :: a
задаёт не массив указателей на объекты вещественного типа, а указатель на вещественный массив.
Однако, ситуация разрешима в рамках стандарта F2003.
Для этого необходимо описать структуру, содержащую поле — указатель на процедуру соответствующего вида.
После чего организовать массив таких структур. Соответственно, после присвоения указателей, вызов процедуры будет выглядеть как обращение к полю-указателю соответствующего элемента массива.
Чтобы создать указатель на процедуру (поле задаваемой структуры), необходимо описать интерфейс указанной процедуры. Так как процедур у нас несколько, ситуация разрешается через описание абстрактного интерфейса.
В общем виде решение на примере может выглядеть так, как это показано ниже.
funcs.f90
Записываем модуль, содержащий две функции, общий (одинаковый) для них абстрактный интерфейс и новый тип func_pointer, содержащий только одно поле f_pointer — указатель на процедуру, имеющую интерфейс наших функций.
module funcs
implicit none
! Описываем универсальный (абстрактный) интерфейс
! для используемых процедур
abstract interface
function func (a,b) result (c)
real :: a, b, c
end function func
end interface
! Вводим новый тип, задающий указатель на процедуру,
! описанную в интерфейсе
type func_pointer
procedure (func), pointer, nopass :: f_pointer
end type
contains
! Задаём пару функций для примера.
function plus (x,y) result (p)
real :: x, y, p
p = x + y
end function plus
function minus (x,y) result (m)
real :: x, y, m
m = x-y
end function minus
end module funcs
main.f90
В основной программной единице описываем массив типа func_pointer, размещаем его и присваиваем полю f_pointer каждого из элементов массива указатель на соответствующую функцию. Теперь вызов функции может осуществляться через обращение к массиву functions с указанием индекса и поля-указателя.
program test
use funcs
implicit none
! Создаём массив типа func_pointer -- массив
! указателей на процедуры
type(func_pointer), dimension(:), allocatable :: functions
integer :: i
real :: x, y
! Размещаем массив и присваиваем его элементам
! указатели на соответствующие процедуры
allocate (functions(2))
functions(1) % f_pointer => plus
functions(2) % f_pointеr => minus
read (*,*) i, x, y
! Вызываем процедуру через указатель по её индексу
write (*,*) functions(i) % f_pointer(x,y)
end program test