albert
albert

Reputation: 1816

How to implement generic interfaces with submodules in Fortran?

My problem is that I have two generic procedures implemented each one in 'mod1.f08' and 'mod2.f08'.

! mod1.f08
MODULE mod1

   INTERFACE func1
      procedure :: foo_int, foo_real
...

! mod2.f08
MODULE mod2

   INTERFACE func2
      procedure :: bar_int, bar_real
...

But I want to join both as submodules of only one module, in this way:

! mod1.f08
MODULE (mainmodule) mod1

   INTERFACE func1
      procedure :: foo_int, foo_real
...

! mod2.f08
MODULE (mainmodule) mod2

   INTERFACE func2
      procedure :: bar_int, bar_real
...

! mainmodule.f08
MODULE mainmodule

    INTERFACE
       procedure :: func1
       procedure :: func2
    END INTERFACE
    ...

Is it possible to do something like this?

Upvotes: 1

Views: 1049

Answers (1)

Scientist
Scientist

Reputation: 1845

Is this what you intend to achieve?

module Main_mod

    interface
    module subroutine foo(dummyReal)
        real, intent(in) :: dummyReal
    end subroutine foo
    end interface

    interface
    module subroutine bar(dummyInt)
        integer, intent(in) :: dummyInt
    end subroutine bar
    end interface

    interface genericFunc
        module procedure :: foo, bar
    end interface genericFunc

end module Main_mod

submodule (Main_mod) SubMain1_smod
contains
    module subroutine foo(dummyReal)
        real, intent(in) :: dummyReal
        write(*,"(*(g0,:,' '))") "This is from inside foo @SubMain1_smod: dummyReal = ", dummyReal
    end subroutine foo
end submodule SubMain1_smod

submodule (Main_mod) SubMain2_smod
contains
    module subroutine bar(dummyInt)
        integer, intent(in) :: dummyInt
        write(*,"(*(g0,:,' '))") "This is from inside bar @SubMain2_smod: dummyInt = ", dummyInt
    end subroutine bar
end submodule SubMain2_smod

program hello
    use Main_mod, only: genericFunc
   call genericFunc(1.)
   call genericFunc(1)
end program Hello

Here is a test output:

> ifort main.f90 -o run.exe
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.4.245 Build 20190417
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.22.27905.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:run.exe
-subsystem:console
main.obj

> run.exe
This is from inside foo @SubMain1_smod: dummyReal =  1.000000
This is from inside bar @SubMain2_smod: dummyInt =  1

The generic procedures have to have their interfaces in the main module and the implementation goes inside the submodules. If the procedure implementations are too large, I'd separate the submodules from the main module and put them in separate files. This will also avoid the compilation cascade by make software if any changes only occur to the submodules and not the interfaces in the main module. (I do it in general for any submodule size). If the procedure interfaces are also too large (with too many dummy input/output arguments), you could also avoid duplicate interface for each of the procedures (once in the main module and the other inside the submodules in the implementation of the procedures) via the procedure keyword in the submodules like the following,

module Main_mod

    interface
    module subroutine foo(dummyReal)
        real, intent(in) :: dummyReal
    end subroutine foo
    end interface

    interface
    module subroutine bar(dummyInt)
        integer, intent(in) :: dummyInt
    end subroutine bar
    end interface

    interface genericFunc
        module procedure :: foo, bar
    end interface genericFunc

end module Main_mod

submodule (Main_mod) SubMain1_smod
contains
    module procedure foo
        write(*,"(*(g0,:,' '))") "This is from inside foo @SubMain1_smod: dummyReal = ", dummyReal
    end procedure foo
end submodule SubMain1_smod

submodule (Main_mod) SubMain2_smod
contains
    module procedure bar
        write(*,"(*(g0,:,' '))") "This is from inside bar @SubMain2_smod: dummyInt = ", dummyInt
    end procedure bar
end submodule SubMain2_smod

program hello
    use Main_mod, only: genericFunc
   call genericFunc(1.)
   call genericFunc(1)
end program Hello

This will generate an identical binary, but the implementation is shorter. However, I personally do not like it, as it often requires you to look at the parent module (which is typically in a separate file) for any dummy argument information. I hope that I understood your question correctly.

Upvotes: 1

Related Questions