Fortran generic interface procedure with optional arguments
Fortran 2018 added syntax useful for polymorphism including
select rank,
which allows rank polymorphism and
select type,
which allows class polymorphism.
For reference, GCC ≥ 7 has select type
and GCC ≥ 10 has select rank
.
Intel oneAPI supports both.
To be compatible with older compilers as well as handle cases where it’s simply more concise to use Fortran 2003 generic procedure interfaces, each procedure must be
unambiguously distinguishable.
Several criteria make a procedure distinguishable.
Here we focus on having at least one non-optional
argument that is TKR-distinct (Type, Kind, Rank).
Notice that this example has the first variable non-optional to make the procedures TKR-distinct.
module mod1
implicit none (type, external)
interface manyranks
procedure m0,m1
end interface manyranks
private
public :: manyranks
contains
subroutine m0(val1, val2)
real, intent(in) :: val1
real, intent(in), optional :: val2
!! omitted code
end subroutine m0
subroutine m1(val1, val2)
real, intent(in) :: val1(:)
real, intent(in), optional :: val2(:)
!! omitted code
end subroutine m1
end module mod1
The code will compile as above.
If you add optional
to both “val1”, the compilation will fail like:
- GCC:
Ambiguous interfaces in generic interface 'manyranks' for 'm0' at (1) and 'm1' at (2)
- Intel:
#5286: Ambiguous generic interface MANYRANKS: previously declared specific procedure M0 is not distinguishable from this declaration. [M1]
Although this example used rank polymorphism, the same issue arises when using any of type, kind or rank (TKR) generic procedures–there must be an unambiguous resolution with at least one non-optional argument. This polymorphism is implemented at runtime, and so there is no guarantee of non-ambiguity when all arguments are optional.