When using Object Oriented structures in Fortran, I am trying to assign a generic function to a structure as follows:
!>================================================
type:: PropEq
!>------------------------------------------------
real(dp) :: coeffs(4)
contains
procedure, pass :: compute => computePhysicalProperty
!>------------------------------------------------
end type PropEq
!>================================================
With the interface of the generic subroutine as follows:
!!>================================================
interface computePhysicalProperty
!!>------------------------------------------------
module procedure computePhysicalProperty_scalar
module procedure computePhysicalProperty_array
!!>------------------------------------------------
end interface computePhysicalProperty
!!>================================================
And the two functions:
!>================================================
function computePhysicalProperty_scalar(propEq, T) result(value)
!>------------------------------------------------
real(dp) :: value
class(PropEqAbstract) :: propEq
real(dp), intent(in) :: T
real(dp), allocatable :: a(:)
a = propEq% coeffs
value = a(1) + a(2)*T + a(3)*T*T + a(4)*T*T*T
!>------------------------------------------------
end function computePhysicalProperty_scalar
!>================================================
!>================================================
function computePhysicalProperty_array(propEq, T) result(value)
!>------------------------------------------------
real(dp) :: value
class(PropEqAbstract) :: propEq
real(dp), intent(in), allocatable :: T(:)
real(dp), allocatable :: a(:)
a = propEq% coeffs
value = a(1) + a(2)*T + a(3)*T*T + a(4)*T*T*T
!>------------------------------------------------
end function computePhysicalProperty_array
!>================================================
Essentially, I am trying to overload the procedure to allow both scalar and array inputs to the function.
When doing so, I get the following error:
error #8182: The name is neither an abstract interface nor a procedure with an explicit interface. [COMPUTEPHYSICALPROPERTY]
Additionally, I have found the following which seems to work: Generic type-bound procedures with procedure arguments
!>================================================
type:: PropEq
!>------------------------------------------------
real(dp) :: coeffs(4)
contains
procedure, pass :: compute_scalar => computePhysicalProperty_scalar
procedure, pass :: compute_array => computePhysicalProperty_array
generic :: compute => compute_scalar, compute_array
!>------------------------------------------------
end type PropEq
!>================================================
Why do the procedures need to be declared explicitely in the type?
Is there a way to use an interface to reduce the type to the following?
????? :: compute => computePhysicalProperty
Thank you
Compiler: Intel
IDE: Visual Studio Enterprise
What you tried to do is not allowed by the Fortran language standard. A binding cannot point to a generic interface, it must point to a procedure. Once you have the bindings (type=bound procedures) in your type, you can make a generic binding from them using the generic :: compute =>
.
The standard grammar is the following:
R748 type-bound-proc-binding
is type-bound-procedure-stmt
or type-bound-generic-stmt
or final-procedure-stmt
From that you are interested in
R749 type-bound-procedure-stmt
is PROCEDURE [ [ , binding-attr-list ] :: ] type-bound-proc-decl-list
or PROCEDURE (interface-name), binding-attr-list :: binding-name-list
and then
R750 type-bound-proc-decl is binding-name [ => procedure-name ]
with a constraint
C774 (R750) The procedure-name shall be the name of an accessible module procedure or an external procedure
that has an explicit interface.
That is the ultimate restriction that you are hitting. A procedure name must a name of a procedure, not of a generic procedure.
Note: if => procedure-name does not appear, it is as though => procedure-name had appeared with a procedure name the same as the binding name.