Fortran 2018 added syntax useful for polymorphism including
which allows rank polymorphism and
which allows class polymorphism.
For reference, GCC ≥ 7 has
select type and GCC ≥ 10 has
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
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:
Error: Ambiguous interfaces in generic interface 'manyranks' for 'm0' at (1) and 'm1' at (2)
error #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.