How to make some generic programming in fortran 90/95 working with intrinsic types

fortran, fortran90, fortran95, generic-programming

Solution

You can use the C preprocessor (CPP) in all major Fortran compilers. Usually there is a flag for invoking it (`-cpp` in gfortran) or it is invoked automatically if the file suffix contains capital F (`.F90`, `.F`). The preprocessor allows more powerful inclusion of sources with the usage of macros.

module imod

  use data_type, only: ivalue 

#define T type(ivalue)
#include "template.f90"
#undef T

end module imod


module intmod

#define T integer
#include "template.f90"
#undef T

end module intmod

and template.f90

contains

subroutine printme(a)

  implicit none

  T :: a

  print *,a

end subroutine printme

This is not strict f90 / f95, but it uses a preprocessor, included in the compilers, which produces another (strict f95) source file and it automatically compiles it instead of the original source that contains the macros.

The compilation is then straightforward

gfortran -cpp main.f90

--Edit--

For non-believers, if you want to see some real code using this, check https://github.com/LadaF/fortran-list (disclaimer: my own code). You can use the parametric linked list there as:

list of len(20) character strings:

module str_list

#define TYPEPARAM character(20)

#include "list-inc-def.f90"
contains
#include "list-inc-proc.f90"
#undef TYPEPARAM
end module

list of integers

module int_list

#define TYPEPARAM integer

#include "list-inc-def.f90"
contains
#include "list-inc-proc.f90"
#undef TYPEPARAM
end module

list of some derived type

module new_type_list
  use, new_type_module, only: new_type

#define TYPEPARAM type(newtype)

#include "list-inc-def.f90"
contains
#include "list-inc-proc.f90"
#undef TYPEPARAM
end module

Problem

I would like to program some procedure that will work with different types. I am planning to use the "include" method used in flibs described here and here. I give here a simple exemple. ``` ! -------------------------------------------------------------- ! module data_type type ivalue integer :: v end type type rvalue real(8) :: v end type end module data_type ! -------------------------------------------------------------- ! module imod use data_type, only: T => ivalue include "template.f90" end module imod ! -------------------------------------------------------------- ! module rmod use data_type, only: T => rvalue include "template.f90" end module rmod ! -------------------------------------------------------------- ! module mod use imod, only: & ivalue => T, & iprintme => printme use rmod, only: & rvalue => T, & rprintme => printme private public :: ivalue, rvalue public :: printme interface printme module procedure iprintme module procedure rprintme end interface printme end module mod ! -------------------------------------------------------------- ! program hello use mod implicit none type(ivalue) :: iv type(rvalue) :: rv iv%v=42 rv%v=3.14 call printme(iv) call printme(rv) end program hello ``` with the included file: ``` contains subroutine printme(a) implicit none type(T) :: a print *,a end subroutine printme ``` What bothers me is that it seems only to work with derived type, and not with intrinsic types. If the user of the module mod want to use the printme routine on an simple integer, it is really annoying for him to encapsulate it in a ivalue type and cannot doing: ``` integer :: a=42 call printme(a) ``` Is there any way to extend this method to intrinsic types, or another method that would do it in strict f90/f95 (I don't want to use the "transfer" method because of the data copy) Tanks!

Original source