Question

I am trying to define an interfaced procedure as a type-bound procedure in a Fortran type definition, but it seems it doesn't work as one would expect. Consider the following module:

module example_module
implicit none
private

interface add_them
  module procedure add_them_integer,add_them_real
end interface add_them

type, public :: foo
  integer, private :: a=1,b=2
  real, private :: c=4.,d=5.
contains
  procedure, public :: add => add_them
end type foo

contains
subroutine add_them_integer(self,x)
class(foo), intent(in) :: self
integer, intent(in) :: x
print *,self%a+self%b+x
end subroutine add_them_integer

subroutine add_them_real(self,x)
class(foo), intent(in) :: self
real, intent(in) :: x
print *,self%c+self%d+x
end subroutine add_them_real
end module example_module

and the corresponding program that uses the module:

program example
use example_module
implicit none
type(foo) :: foofoo
call foofoo%add(1)
call foofoo%add(2.)
end program example

I would expect this to compile and results should be 4 and 11. However, gfortran reports the following error:

procedure, public :: add => add_them
         1
Error: 'add_them' must be a module procedure or an external procedure with an explicit interface at (1)

A workaround is to use generic type-bound procedure instead of an interfaced one, so that the module is as follows:

module example_module
implicit none
private

type, public :: foo
  integer, private :: a=1,b=2
  real, private :: c=4.,d=5.
contains
  generic, public :: add => add_them_integer,add_them_real
  procedure, private :: add_them_integer,add_them_real
end type foo

contains
subroutine add_them_integer(self,x)
class(foo), intent(in) :: self
integer, intent(in) :: x
print *,self%a+self%b+x
end subroutine add_them_integer

subroutine add_them_real(self,x)
class(foo), intent(in) :: self
real, intent(in) :: x
print *,self%c+self%d+x
end subroutine add_them_real
end module example_module

This works as expected. However, I cannot use a generic procedure. The above is just a simplified example to demonstrate the problem, but in my actual code 'add_them' cannot be a generic procedure because 'foo' is actually a derived-type and 'add_them' overrides a procedure defined in the parent type; gfortran (at least) does not allow generic procedures overriding base procedures. To bypass this restriction, I thought I should use an interface instead, but as you can see in the above example, although 'add_them' is defined correctly, compiler complains that "'add_them' must be a module procedure or an external procedure with an explicit interface".

Any help would be appreciated; thanks in advance.

Was it helpful?

Solution

The gfortran error for your first section of code is correct. The way to do generic bindings is as per your "works as expected" section of code.

If a parent type has a specific binding with a certain name, then you cannot reuse that name in extensions, other than to override the specific binding.

If you want add (note the name add_them doesn't appear in your second case) to be a generic binding in extensions, then make it a generic binding in the parent.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top