> Hi all fortran gurus !
> I would like to discuss the current methods to manage
> templates in fortran, following the thread
> http://groups.google.com/group/comp.lang.fortran/browse_thread/thread...
> which was very interesting, but showed no details on
> how to pratically manage the source code.
> This feature is very well-known by C++ developers as "templates".
> One example of the problems solved by C++ templates is to
> have a sorting source code which is able to manage for any
> data type, including integers, reals, or even abstract data
> types.
> I currently know 3 ways of dealing with templates in fortran,
> even if none of them is included in any fortran norm
> (and none of them is detailed in a fortran book, to my knowledge) :
> - pre-processing macros,
> - clever use of the "include" statement,
> - m4 macros.
> Let's begin with the pre-processing macros.
> Suppose that the file "sorting_template.f90" contains a template
> sorting module, parametrized by the _QSORT_TYPE macro.
> The following is an example of parametrized argument declaration :
> subroutine qsort ( array, compare )
> _QSORT_TYPE, dimension(:) :: array
> Here "_QSORT_TYPE" may be an integer, a real or any fortran
> derived type.
> This name has been chosen because a fortran variable cannot
> begin with an underscore so that no confusion can occur
> between a preprocessing macro and a variable name.
> Before using the template, one must instanciate it,
> which is done with :
> #define _QSORT_TYPE type(SORT_DATA)
> #include "sorting_template.f90"
> The "instanciation" is based, for example, on the following
> SORT_DATA derived type, which may be defined in the
> module "m_testsorting.f90" :
> type SORT_DATA
> integer key
> integer index
> end type SORT_DATA
> Even if this derived type is quite simple, practical uses of this
> method may include more complex data types.
> The module "m_testsorting" has to be pre-processed before
> being used. After pre-processing, the previous line has
> been transformed to :
> subroutine qsort ( array, compare )
> type(SORT_DATA), dimension(:) :: array
> With this method, generic source code templates can be
> configured at will and allow to generate specific
> sorting algorithms for whatever type of data.
> This method can lead to more complex templates, with
> no limit in the number of macros, that is, no limit
> in the number of abstract data types in the template.
> The main drawback is that the debugging process is not
> possible interactively. This is because the source code
> is generated at compile-time and the "template" does
> not correspond to the post-processed one anymore.
> One solution is to use manually the pre-processor to
> generate the pre-processed template and to debug on that
> later file.
> Two other methods exist to manage to do generic programming
> in fortran : the "include" statement and m4 macros.
> The "include" fortran statement can be used so that the
> target source code contains the definitions of an
> abstract data type used in the template.
> This method is used by Arjen Markus in the Flibs
> library, for example in the linked list abstract
> data structure :
> http://flibs.sourceforge.net/linked_list.html
> Here we suppose that the file "sorting_template.f90"
> contains one sorting subroutine, which arguments
> are defined like this :
> subroutine qsort_array( array, compare )
> type(SORT_DATA), dimension(:) :: array
> The trick is to use the include fortran statement
> to put that template source code into a context in
> which the abstract data type is defined.
> The following source code defines a module, the derived
> type SORT_DATA and then include the template source code.
> module m_testsorting
> type SORT_DATA
> integer key
> integer index
> end type SORT_DATA
> contains
> include "sorting_template.f90"
> end module m_testsorting
> The module m_testsorting is now providing the derived type
> SORT_DATA and the methods to manage it, which are included
> in the template. With a little more work, it is even possible
> to make so that the final derived type has a name which
> corresponds more to the one implemented by the abstraction,
> as shown by Arjen Markus on the linkedlist example.
> module MYDATA_MODULE
> type MYDATA
> character(len=20) :: string
> end type MYDATA
> end module
> module MYDATA_LISTS
> use MYDATA_MODULE, LIST_DATA => MYDATA
> include "linkedlist.f90"
> end module MYDATA_LISTS
> The main advantage of the "include" method is that
> it uses only fortran statements so that the debugging
> process is possible interactively. Moreover, it is very
> elegant.
> Another method is to use m4 macros to generate source code
> at compile-time. Gnu m4 is an implementation of the traditional
> Unix macro processor. This method is used by Toby White the
> in the Fox library :
> http://uszla.me.uk/space/software/FoX/
> The template source code is defined in files which have the .m4.
> extension and the corresponding source code is defined in the
> .F90 file. The source code may be difficult to maintain, but the
> method is extremely powerful, thanks to the m4 features.
> For example, one can use a m4 "for" loop to generate
> several subroutine based on one template subroutine.
> But, as for the pre-processing method, the interactive
> debugging of the .m4 templates is not possible :
> instead, the processed .f90 generated files are debugged easily
> and directly.
> Are there other well-known methods ?
> Is there a definitive drawback for one of these methods so
> that another way should be chosen?
> All comments will be appreciated.
> Best regards,
> Michaėl Baudin
(One remark: part of the code you refer to was written