Tapez la procédure liée comme arguments
-
20-12-2019 - |
Question
Je souhaite transmettre une procédure liée à un type (en tant que fonction externe) à une autre fonction comme suit :
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 produit donne cette erreur :
write(*,*) s(t%f)
1
Error: Expected argument list at (1)
Mais ce que je peux faire c'est :
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
Je pense que le problème est lié à Passer des procédures liées au type comme arguments, mais je ne vois pas pour le moment comment les réponses qui s'y trouvent peuvent m'aider.
MODIFIER:
Un meilleur exemple qui (espérons-le) montre la difficulté :
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
MODIFIER II :Ok, les wrappers fonctionnent toujours en combinaison avec un pointeur :
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
Ce n’est certainement pas une belle solution mais au moins ça marche.
La solution
Vous pouvez écrire un wrapper.Il s'agit de la version la plus simple.Nécessite de transmettre une fonction interne comme argument factice (F2008), mais vous pouvez également déclarer le wrapper dans un module, si le t
peut être là.
Notez que j'ai modifié la déclaration de l'argument de procédure dans s
à quelque chose de plus moderne - le bloc d'interface.
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
La raison de votre erreur est bien décrite dans les réponses à la question liée, vous ne pouvez pas transmettre les procédures liées au type comme vous l'avez essayé.