Reputation: 13
I have a grammar question about Fortran. It seems that Fortran (or gfortran?) cannot assume a returning value of a function defined in an interface block in an abstract interface. I tried to compile the following codes by gfortran (version 9.4.0).
abstract_class.f90:
module module_abstract_class
implicit none
type, public, abstract :: abstract_class
contains
procedure(method_interface), pass(self), deferred :: method
end type
abstract interface
pure function method_interface(self, func, a, b) result(ret)
import abstract_class
class(abstract_class), intent(in) :: self
real , intent(in) :: a, b
real :: ret
interface
pure function func(a, b) result(ret)
real, intent(in) :: a, b
real :: ret
end function
end interface
end function
end interface
end module
extend_class.f90:
module module_extend_class
use module_abstract_class
implicit none
type, extends(abstract_class) :: extend_class
contains
procedure, public, pass(self) :: method
end type
contains
pure function method(self, func, a, b) result(ret)
class(extend_class), intent(in) :: self
real , intent(in) :: a, b
real :: ret
interface
pure function func(a, b) result(ret)
real, intent(in) :: a,b
real :: ret
end function
end interface
ret = func(a, b)
end function method
end module
main.f90:
program i_love_fortran
use module_extend_class
type(extend_class) :: e
print *, e%method(add, 1, 2)
contains
pure function add(a, b) result(ret)
real, intent(in) :: a, b
real :: ret
ret = a + b
end function
end Program i_love_fortran
shell:
gfortran abstract_class.f90 extend_class.f90 main.f90
But, I could not compile this code due to the following errors.
gfortran abstract_class.f90 extend_class.f90 main.f90 extend_class.f90:8:17:
8 | procedure, public, pass(self) :: method
| 1
Error: Argument mismatch for the overriding procedure ‘method’ at (1): Type mismatch in argument 'func' (UNKNOWN/REAL(4)) extend_class.f90:6:49:
6 | type, extends(abstract_class) :: extend_class
| 1
Error: Derived-type ‘extend_class’ declared at (1) must be ABSTRACT because ‘method’ is DEFERRED and not overridden main.f90:2:8:
2 | use module_extend_class
| 1
Fatal Error: Cannot open module file ‘module_extend_class.mod’ for reading at (1): No such file or directory compilation terminated.
I think "func" defined in "method" should be REAL(4). Why does Fortran/gfortran assume that "func" is UNKNOWN type?
Upvotes: 1
Views: 143
Reputation: 1416
Your func
is just another abstract interface
, because id defines what the actual pure function will be like when the function called. So, you should include it just as also an abstract interface
and make it public so other modules can access it.
Then, you reference it as a function dummy argument using
procedure(func_template) :: func
This now works:
module module_abstract_class
implicit none
type, public, abstract :: abstract_class
contains
procedure(method_interface), pass(self), deferred :: method
end type
interface
end interface
abstract interface
pure function func_template(a, b) result(ret)
real, intent(in) :: a, b
real :: ret
end function func_template
pure function method_interface(self, func, a, b) result(ret)
import abstract_class,func_template
class(abstract_class), intent(in) :: self
real , intent(in) :: a, b
procedure(func_template) :: func
real :: ret
end function
end interface
end module
module module_extend_class
use module_abstract_class
implicit none
type, extends(abstract_class) :: extend_class
contains
procedure, public, pass(self) :: method
end type
contains
pure function method(self, func, a, b) result(ret)
class(extend_class), intent(in) :: self
real , intent(in) :: a, b
procedure(func_template) :: func
real :: ret
ret = func(a, b)
end function method
end module
program i_love_fortran
use module_extend_class
type(extend_class) :: e
print *, e%method(add, 1.0, 2.0)
contains
pure function add(a, b) result(ret)
real, intent(in) :: a, b
real :: ret
ret = a + b
end function
end Program i_love_fortran
Upvotes: 0