User:RBaSc/draft ftnoo

= Putting Fortran's object-related features to practical use = This article describes how advanced Fortran language features can be applied toward object-based and object-oriented programming techniques. These are, of course, to a significant extent a matter of taste, personal style and possibly overarching program design considerations, so should be taken with a pinch of salt.

Language features from Fortran 95 and later will be used; those from Fortran 2003 and later will also be shortly described. They are explained in more detail in e.g., Metcalf, Reid, Cohen and Bader. See also Fortran 95 language features for the language's fundamentals; the prerequisite for understanding this article is that features explained there are well understood.

Boldface will be used where term definitions are introduced. They are additionally annotated by "(not a Fortran term)" or similar if the term is not used in the Fortran standard itself, but is in general use in the technical literature.

Compilable and runnable example code is available from an external Github repository.

Introduction: Container-like types
The word "Container-like" is not a Fortran term, but used in the context of this article to designate types with components whose size (or type, to be discussed later) is not known when the type is declared. For deferred sizing of array objects, this can be achieved by using either the  or the   attribute for the component's specification.

The language features and programming techniques will be shown using two examples introduced in the following section. The demonstration codes for this chapter can be found in the  folder of the Github repository.

Allocatable components
As an example for the type definition of a value container (not a Fortran term) with an  component consider An object declared to be of this type  is suitable for characterization of a polynomial

$$p(x) = \sum_{k=0}^{degree} a_{k} \cdot x^k \quad (x \in \Re) $$

once it has been created and subsequently supplied with values of the coefficients:

Pointer components
As an example for the type definition of a reference container (not a Fortran term) with a  component consider Note that referencing the type itself when declaring a component is permitted if that component has the   or   attribute; such types are generally known as recursive. They are used to represent information structures (lists, trees, ...), often with specific relationships between the individual data entries stored in each node. In this example, the assumption is that entries of type  in subsequent list items fulfill an ordering condition, based on the functionality supplied with that type:   Given that Fortran supports arrays, use of simple linked lists is in most cases inappropriate. The example is presented here as being the simplest that permits illustrating the language features of interest.

An object declared to be  is suitable as starting point for building a linked list with node entries of type. In the simplest case, inserting a data item into the object is done by executing the following statements: However, as we shall see below, setting up a complete and valid  object in a reliable manner needs additional work.

Constructing objects of container-like type
The semantics of the default structure constructor for container-like objects needs to account for any additional  or   attribute specified for type components.

For the first example type from the last section, the executable statements in result in an object  auto-allocated to the value , and an object   with   unallocated.

For the second example type from the last section, the executable statements in result in an object   with   pointer associated with , and an object   with   disassociated; the   components of both objects have values,   and  , respectively. Note that an argument that matches with a  component must have either the   or the   attribute. Also, keyword notation can be used in structure constructors in the same manner as for procedure arguments.

The default constructor's behaviour has some properties that one needs to be aware of:


 * 1) If all type components have the   attribute i.e., the type is opaque (not a Fortran term), it can only be used if the type declaration is accessed by host association (this is the same as for nonallocatable/nonpointer components);
 * 2) especially for container-like types, its semantics may be incompatible with the programmers intentions for how the objects should be used.

Item 2 is illustrated by the above object setups, specifically:


 * In the  example given above, the lower bound of   is set to 1, contrary to the expectation that it should be 0. One could account for this by calculating index offsets in any module procedures that process   objects, but this makes the code harder to understand and maintain. Also, the degree of the polynomial should be determined by the last nonzero entry of the coefficient array, but the language can of course not be aware of this.
 * In the  example given above, the ordering requirement for entries in subsequent nodes is not checked, so will usually be not fulfilled. Also, if   goes out of scope before   does, the list structure is torn to bits.

The programmer can enforce appropriate semantics by overloading the structure constructor. In this case, it is usually a good idea to declare the types as being opaque.

Overloading the structure constructor is done by


 * creating a named interface (i.e., a generic function) with the same name as the type of interest;
 * creating at least one specific function (a subroutine is not permitted), usually returning a scalar result of the type of interest.

For the  type the interface block (placed in the specification section of the module containing the type definition) might read and the implementation of   (in the   part of the module) might read Because its signature matches the default structure constructor's, the function actually overrides the default constructor, making it generally unavailable.

For the  type the interface block might read with the implementation of   as follows: The constructor has a signature that differs from that of the default one, but the latter is unavailable outside the host scope of the type definition anyway, due to the opacity of.

Copying objects of container-like type
Default assignment extends to container-like objects. For objects declared as and after defining values for prospective right-hand sides, execution of the statement produces the same result as and execution of the statement produces the same result as  The terms deep copy and shallow copy (neither are Fortran terms) are sometimes used to describe the above behaviour for   and   components, respectively. Note that - different from the default structure constructor - having  components does not affect the use of default assigment. However, the semantics of default assignment might not be what is needed from the programmer's point of view.

Specifically, consider the case where the object  above has previously been set up by invoking the overloaded constructor. The assignment above would then have the following effects:


 * 1) The list elements of the original , beginning with  , would become inaccessible ("orphaned"), effectively causing a memory leak;
 * 2) after the assignment statement,   references into , resulting in aliasing.

To avoid 2., it is possible to overload the assignment operator for reference containers to create a deep copy. Note that in the case where defined unary or binary operations are introduced, the functions that define these need to create deep copies to create the result variable anyway, otherwise things simply don't work. The downside of this is that in code like - with the overloaded concatenation operator meaning that the argument lists are joined - multiple deep copies need to be done (the implementation of the module procedure  that supplies the necessary specific for   is not shown here; see the source   for details). It turns out that some of these exist only intermediately.

Here an implementation of the specific procedure for the overloaded assignment of  objects: Avoiding 1. is usually done by means of finalizers, to be discussed in the next section. This is because assignment is not the only possible cause for orphaning of -related memory (or indeed other resource leaks).

Finalization and conclusions
To deal with resource leaks that are otherwise not within the programmer's means to avoid, a type definition can be connected with a user-defined final procedure that is automatically invoked in certain situations. For the  type, this would look like Note that the   statement appears after a   statement in the type definition; this implies that   is not a regular type component. The module procedure's implementation might then be as follows: It must be a subroutine that takes a single argument of the type to be finalized. Most additional attributes are not permitted for that dummy argument; for the case of finalizing array arguments it is possible to have a set of finalizers (all listed in the type definition), each of which declares the dummy argument with an appropriate rank.

The  and   properties specified above reflect the specific needs for the   type and its associated procedures. The  specification is optional (i.e., procedures can be called recursively by default), but a   specification can be supplied if the implementation's semantics does not permit correct behaviour in recursive calls.

The finalizer will be automatically invoked on an object if


 * 1) it appears on the left-hand side of an intrinsic assignment statement (before the assignment is performed),
 * 2) on invocation of a procedure call where it is argument associated with an   dummy,
 * 3) it is a non-saved variable and program execution ends its scope, or
 * 4) it is deallocated.

Nonpointer nonallocatable function results fall into the third category above; however, finalization does not apply for the default structure constructor.

Note that if a finalizer is defined and the constructor is overloaded, but the assignment operator is not, then the assignment statement  (which then translates into a single function call to the   function shown earlier) will result in a mutilated left-hand side, because the finalizer will be executed on the function that overloads the constructor, resulting in   being disassociated. For this reason, the following guideline applies: See also the article "Rule of three" for the analogous situation in C++.

Extended semantics for allocatable objects
Scalars can have the  attribute: Allocation then can be done explicitly; the following examples illustrate applications of the   statement that are useful or even necessary in this context: Typed allocation is necessary for the string variable, because the length parameter of a string is part of its type; we will later see that derived types can also appear in the type specification. Sourced allocation permits the creation of an allocated object that is a clone of the specified source object or expression.

Alternatively, allocatable objects (be they scalar or arrays) can be auto-allocated by appearing on the left-hand side of an intrinsic assignment statement: A caveat is that for overloaded assignment, this will usually not work - either one needs to explicitly allocate the object before assigning to it, or sourced allocation must be used, which bypasses the overloaded assignment.

Note that for allocatable objects with deferred-size entries (e.g., strings, arrays) a non-conformable left-hand side in an assignment statement will be deallocated before being allocated to the right length or shape, respectively.

The features discussed in this subsection are also useful for object-oriented programming, with additional semantics applying for the case of polymorphic objects.

Implementing move semantics
Sometimes it may be necessary to make use of move instead of copy semantics i.e., create a copy of an object and then getting rid of the original. The simplest way of doing this is to make use of allocatable (scalar or array) objects, After  has been set up, the object's content can then be transferred to   by using the   intrinsic,  which will deallocate   if necessary, before doing the transfer. After the invocation,  will have the value formerly stored in , and   will end up in the deallocated state. Note that the latter does not involve a regular object deallocation (effectively, a descriptor for the object is moved), so any existing finalizer will not be invoked.

The construct
The above rules on finalization imply that variables declared in the specification part of the main program are not finalizable, since they by default have the  attribute. One could argue this is not necessary since all assigned memory is reclaimed when program execution ends. However, excessive memory consumption or the use of other resources may cause issues for reliable program execution. To work around these, the  construct can be used: The construct (as the only one in Fortran) permits declaration of non-saved variables in its specification part. Their lifetime ends when program execution reaches the  statement, and they therefore are finalized at this point, if applicable. Named variables declared outside the construct are accessible inside it, unless a block-local declaration with the same name exists.

Note that the construct's execution flow can be modified by executing an  statement in its body; this can, for example, be used for structured error handling and finally permits sending   to retirement.

The construct
With the introduction of deeply nested derived types, code that needs access to ultimate components can become quite hard to read. An  block construct that enables the use of auto-typed aliases can be used. This is illustrated by a procedure that is used to implement the multiplication of two polynomials:

For the duration of execution of the construct, the associate names can be used to refer to their selectors (i.e., the right-hand sides in the association list). If the selectors are variables, so are the associate names (, ,   in the above example), and can be assigned to. If the selectors are expressions, so are the associate names (,  in the above example).

Associated entities that refer to variables inherit the,  ,  ,   and   attributes from their selectors, but no others. An associate name can only refer to an  dummy argument if the latter is present. Associate names can also appear in other block constructs, which will be discussed where appropriate.

Performing I/O with objects of container-like type
For objects of container-like type, a data transfer statement would fail to compile, since the run-time library is incapable of dealing with the irregular structures that are hiding behind the innocuous variable. Language features for user-defined derived type I/O (UDDTIO) permit the programmer to control the data transfer in an appropriate manner. This is achieved by binding an I/O statement on a derived-type object to a user-defined procedure, for example through a suitably written named interface: Note that this also applies to data types for which the above stand-alone statement is permitted, and then overloads the default I/O mechanism.

Once the binding is properly defined, the above I/O statement is accepted by the compiler, and its execution causes the user-defined procedure to be invoked. Therefore it is called the parent I/O statement. The actual data transfer statements that are issued inside the user-defined procedure are called child I/O statements.

The following interface variants are permitted, with the obvious interpretation:



The self-defined procedure is restricted with respect to its interfaces' characteristics, which are described in the following: The placeholders  and   must be replaced by a specific procedure name referenced in the generic interface.

The dummy arguments' declarations and meaning are:


 * : Must be declared to be a nonpointer nonallocatable scalar of the type in question. If the type is extensible (to be explained later), the declaration must be polymorphic (i.e. using ), otherwise non-polymorphic (using  ). Its   must be   for , and " " or " " for  . It represents the object on which data transfer statements are to be executed.   Note: For the examples in this chapter, we need to use  , but the behaviour is as if   were used, as long as the actual arguments are non-polymorphic and the procedure-based interface is used for the invocation.
 * : An  scalar with  . Its value is that of the unit used for data transfer statements. Use of other unit values is not permitted (except, perhaps,   for debugging purposes).
 *  : A  string with  . This can only appear in procedures for formatted I/O. The following table describes how the incoming value relates to the parent I/O transfer statement:

Additional properties and restrictions for UDDTIO are:
 * : A rank-1 assumed-shape  array with   . This can only appear in procedures for formatted I/O. The incoming value is taken from the final part of the   edit descriptor; in the example from the table above it would have the value [10,2]. Free use can be made of the value for the disposition (formatting, controlling) of I/O transfer statements inside the procedure. The array's size may be zero; specifically, it will be of size zero for the listdirected or namelist cases.
 * : An  scalar with  . It must be given a value consistent with those produced by non-UDTTIO statements in case of an error. Successful execution of the I/O must result in a zero value. Unsuccessful execution must result in either a positive value, or one of the values   or   from the   intrinsic module.
 * : A  string with  . It must be given a value if a non-zero   is returned.


 * All data transfers are executed in non-advancing mode. Any  specifier will be ignored;
 * asynchronous I/O is not supported;
 * Inside the user-defined routine, no file positioning statements are permitted.

The following demonstrates a partial implementation of formatted writing on  objects: Notes:


 * The namelist itself is inaccessible from the procedure; it is not needed since the procedure only needs to write the list values in a suitably formatted way. Termination of the list is indicated by a final logical value of 'F' in the list entry of the namelist file; the termination information must be appropriately processed in the corresponding namelist case of the read procedure.
 * The example implementation does not support  editing; invoking the parent I/O statement from the above table would therefore cause error termination unless an   argument is added to it.

Introduction: Establishing an explicit relationship between types
The discussion on object-based program design in the previous chapter was based on creating derived types that are comprised of objects of other types (intrinsic or derived); this is also known as type composition (not a Fortran term). For object-oriented programming, the approach is that a closer relationship between two (or maybe more) types can be established through language-defined mechanisms, on both the levels of type definition and object declaration and use. Fortran supports a single inheritance model, which will be outlined in the following sections; runnable example codes are supplied in the  subfolder of the Github repository

Extension types
As a starting point, consider the definition of a type, an object of which can quite generally represent a physical body: This might come along with procedures that impose a momentum change or a change of mass on a  object: After writing lots of code that makes use of the above, imagine that you now want to deal with objects that have the additional property of electric charge. One could, of course, simply add another component to the original  type, but in most cases this would invalidate existing code which would need to be corrected, recompiled and retested. Furthermore, all  objects would require the extra memory, which for the existing codebase would simply be wasted. It is more convenient and less intrusive to create a new type that is an extension of the existing one (the parent type): An object of this type would then have the following type components:



that are inherited from the parent type, and the additional type component



that was added in the definition of. Furthermore, it is also possible to reference that part of the object corresponding to the parent type, which is a subobject of just that type:



Correspondingly, there are various manners in which the default structure constructor can be used to create a defined value: Any derived type that does not have the  or   attributes can be extended in the above manner; specifically, an extension type can itself be extended. For any given "base" type this gives rise to a potential hierarchy of types that can be represented by a directed acyclical graph:

An object of type  is type compatible with both   and , so any of these two can, for example, appear in a call to the procedure.

Declaring entities with
By declaring an object with the  instead of the   specifier, is is possible to defer the actual type that an object has to be determined when the program executes, or even have the actual type change during program execution. Such an object is designated as being polymorphic. To be polymorphic, an object must fulfill one of the following prerequisites:


 * it has the  attribute,
 * it has the  attribute, or
 * it is a dummy argument (with or without a  or   attribute).

For example, the typed alllocation statement executed on a polymorphic allocatable object causes the object  that has the declared type   to be allocated with the dynamic type  ; in Fortran nomenclature, the latter term denotes what was referred to above as "actual" type.

For an unallocated allocatable or a disassociated pointer the dynamic type is considered to be the same as the declared type, although this is only useful in very few contexts that do not require the object to be allocated or associated.

Run-time type and class identification
Within the scope of the object's declaration, only the components of its declared type are accessible. Also, I/O operations on a polymorphic object are not permitted, unless UDDTIO routines have been defined. One way to obtain access to the complete object is to use a construct that permits run-time type identification (not a Fortran term),. For example, the I/O statements in are permitted, since inside the block for each type guard the object is non-polymorphic and of the specified type. At most one type guard can match the object's type, and the corresponding statements are executed; otherwise the  section is executed (and the object remains polymorphic there). A disadvantage of using  is that it needs to be appropriately updated whenever an additional type extension is defined; apart from the maintenance effort this also requires access to all source code that contain a relevant instance of the construct. For this reason, type-bound procedures (to be discussed) should be preferably used to gain access to additional type components.

For updates of the  component of a   object, one now could consider the following: However, invoking this subroutine in the usual Fortran 95 style will not work for the variable , since it violates the rule that the dummy argument's declared type must be type compatible with the actual argument's declared type. One can work around this by using a  construct with run-time class identification (not a Fortran term), based on writing class guards instead of type guards: The   procedure will then be invoked if the dynamic type of   is   or an extension of it. The object remains polymorphic inside the class guard, only its declared type changes to that specified in the guard. Unless the "lifted" declared type of interest is already otherwise known from the context, or handling the  fall-through is straightforward, this is not in general a desirable way of dealing with class mismatches.

It is permitted to mix type and class guards in a  construct; in that case, a type guard has precedence over a class guard specifying the same type with respect to selection of the guarded statements to be executed.

Unlimited polymorphic objects
A special case of polymorphism is that an object can be unlimited polymorphic. Such an object, declared with, can be of any dynamic type (intrinsic type, extensible derived type,   or   derived type), as illustrated by the following statements: Accessing the object's data always needs a   construct; type guards in the construct can in this case might not only refer to extensible types, but also to intrinsic types. However, for  or   derived types, no type resolution is possible - these always fall through to a   guard, if present; use of unlimited polymorphic objects to store values of such types is therefore considered unsafe.

In this context, allocation with  allocates the target object to the source object's dynamic type before copying its value to the target object. If the source object's data is not needed,  can be used instead. Sourced allocation becomes a powerful tool, since the dynamic type of the source object need not be known in the scoping unit within which the allocation is executed.

Type components with the  or   attribute can be unlimited polymorphic, enabling the construction of generic and potentially inhomogeneous container-like types. As an illustration of this, a supporting type for the purpose of holding data targeted for manipulation of other objects is presented; its definition (placed in the module ) reads where   will refer to the property that needs updating, and   will contain the data to be used for the transaction. Because the  component should be able to represent any type, it is declared as being unlimited polymorphic. Because the  component might hold data needed to produce an array of arbitrary shape, the additional   component is supplied, but its use is really only necessary if objects of rank at least 2 must be dealt with. The structure constructor for that type has been overloaded to work around compiler bugs and make handling of scalar data easier. The following example illustrates how to establish a simple interface for setting components of a structure: Notes:
 * Having this simple interface at the cost of significant additional setup code might at first sight appear frivolous; however, once type extension is used on a larger scale, setting or modifying further components in the conventional way becomes rather irksome without a concept like that above, especially if type-bound procedures with a simple and uniform interface must be implemented;
 * The object  remains unchanged in case an unsuitable value is provided for  . One could add explicit error handling, but for these examples this is considered an unnecessary complication;
 * The permitted values for the  object should be documented for each procedure that takes such an object;
 * Because access to  within   is via a type component, one is obliged to introduce an associate name for the latter. The language rules only permit omitting the associate name for named variables, and subobjects are not named variables;
 * A rank-changing pointer assignment is used to transform the rank-1  array to an object that can be assigned to a rank-2   array; this works because the right-hand side is a rank-1 object; for rank-2 and higher the rank-changing pointer assignment will only work if the target assigned to is a simply contiguous array designator (a topic not covered here). Note that in this context, the   intrinsic cannot be used because it requires the size of its   argument to be a constant.

The program invoking the  procedure might do so as follows, to set up a   object:

Type-bound procedures (TBP)
To resolve the class mismatch issues arising from the use of polymorphic objects, one needs a language mechanism for making a run-time decision on a procedure invocation that depends on the dynamic type of a polymorphic object. This can be achieved by binding a procedure to a type in the type definition via a  statement in the type's   part. For the type, the augmented type definition reads This does not impact how the structure constructor is used; for this, only the specifications before the   statement are relevant. To establish a simple and uniform interface for object updates, the procedure  makes use of the   type discussed earlier, which in view of the context is locally renamed to  :  In its interface, the passed object   must be declared to be a polymorphic scalar, with its declared type being the one the procedure has been bound to. The implementation reuses existing code where possible (very simple in this example, but this is of course not generally the case), to avoid the need for extensive revalidation.

Invocation of the procedure could be done in the usual manner, but the preferred style, especially in the case that the actual argument is polymorphic, is to do it through the object itself: For polymorphic objects, the procedure  will be invoked if the dynamic type of the object is   (this might not be true if the dynamic type is an extension, as we shall see).

The invocation can also be done with non-polymorphic objects; in this case, the binding could (in principle) be determined at compilation time, potentially saving some call overhead. Note that the passed object dummy is not permitted to be allocatable or a pointer, which facilitates this usage.

So far this is not particularly interesting; the key thing is what happens once we turn to type extensions. For example, to enable modification of the  component (in addition to that of other components) of an object of dynamic type , it is possible to override the parent type's bound procedure: with the procedure defined as follows: The overriding procedure must use the same interface as the overridden procedure, except that the passed object is declared to be of the extended type; even the argument keywords must be the same. Once the override has been defined, the call through an object of dynamic type  will be dispatched to  :  Notes:


 * for the above example, direct invocation of the procedure  is not possible (as already noted earlier);
 * the second TBP call illustrates the invocation of the parent object update from . Without this, changes that impact the parent object would not be done. By implementing this consistency of behaviour, the programmer assures that the inheritance hierarchy adheres to the Liskov substitution principle;
 * to enforce using the TBP calls in a use association context, the module procedures that implement them can be made . The accessibility of the TBP itself is determined by the attribute for it (default is  ) in the type definition;
 * the programmer can prevent overriding of a binding by declaring it to be ; its implementation then is regarded as valid for all conceivable extension types.

Abstract types and interfaces
The  type used for demonstrating the   functionality in the object-based chapter's example was set up as a fixed container-like type. It is desirable to be able to use the list machinery more flexibly i.e., for any type that supports the "less-than" comparison. This can be achieved by introducing an abstract type with a deferred binding. It is not possible to create an object whose dynamic type is abstract, or a non-polymorphic object of abstract type. For this reason, the deferred binding cannot represent an existing procedure, but is characterized by an abstract interface: The  statement is required to give the interface access to the type defined in its host. Furthermore, an override of the structure constructor will be needed that permits creation of polymorphic   objects. The details of this will be described later (since, indeed, a devil lurks in these details). Note that the above combined use of abstract types and interfaces is also known under the (non-Fortran) term interface class.

This framework permits the programmer to implement the following programming technique, which is also known as dependency inversion (not a Fortran term):


 * 1) Any machinery that makes use of polymorphic   objects is made to only refer to the above abstractions. For example, the definition of the   type could be adapted to read The advantage of this is that no change to the preexisting machinery will be needed whenever a programmer decides to add an extension type as outlined in 2. below.
 * 2) For a concrete realization of a   object, the programmer needs to create a type extension, for example including an obligatory implementation   of an overriding TBP for the deferred binding. The constructor function (promised earlier, but not yet delivered) also needs to be updated to enable creation of objects of the extended type.

Generic type-bound procedures and operator overloading
As a convenience, use of an overloading for the comparison operator "<" can be provided by creating a generic type-bound procedure: which means that when a statement involving a comparison expression is executed, the overridden type-bound procedure bound to the first operand will be invoked to evaluate the expression. It is not necessary to re-specify the  clause in any type extensions; the dispatch will automatically select the overridden procedure.

Named generic type-bound procedures that do not overload existing operations can also be defined; an example for this is given in the section "Functions with parameters". The rules for generic resolution work similar as for nonpolymorphic generic procedure interfaces, with the additional restriction that polymorphic dummy arguments that are related by inheritance cannot be distinguished for the purpose of compile-time resolution to a specific procedure.

Discussion of structural dependencies
When implementing the above concept, typically a separate module, say, is created for some or all of the extension types of. The motivations for this can be:


 * avoid recompilation of any machinery that makes use of the  module;
 * the source code of  might not be readily modifiable;
 * prevent  from turning into a monster module in case large concepts are implemented through extension types, or many extension types are created.

The implementation of the constructor will need to use associate  since it needs to be able to create objects of the types defined there. On the other hand, the interface to the constructor needs to be visible in, since the machinery that depends on it must be able to call it. As a consequence, one would end up with a circular  dependency between the two modules, which is prohibited.

Using submodules to break dependency cycles
To deal with such a situation (among others), the concept of submodule is available. This is a type of program unit that serves as an extension to an existing module (or submodule), to which it has access by host association. Furthermore, submodules allow the programmer to separate interfaces from implementations; the former are defined in the parent program unit (i.e., the program unit of which the submodule is an extension), the latter in the submodule itself.

For the constructor function, the following interface block can be declared in : The special notation   (or   for a subroutine) tells the compiler that the implementation is deferred to a submodule.

Notes:


 * the above interface requires no reference to any entities contained in ;
 * consistent with this, the variable representing the function result is an allocatable polymorphic object of the abstract type;
 * an  statement is not obligatory in separate module procedure interfaces, although it is permitted (compiler support assumed!), primarily for the purpose of  fine-grain control of host access;
 * the type  is, again, a renamed version of the   type referred to earlier.

Implementation of the constructor
The submodule containing the implementation then reads as follows: Notes:


 * The interface for the separate module procedures is omitted, since it can be deduced from its specification in the parent module. However, alternative syntax exists that replicates the interface (but this is not shown here);
 * the effect of the  clause is to suppress use access to any entity of the parent program unit (which would be indirectly established). This is because use association overrides host association, which may cause undesirable side effects;
 * submodules additionally can contain specifications (before the  statement), as well as local submodule procedures. All these are only accessible from the submodule (and its descendant submodules, if any);
 * the naming scheme for a submodule always references the direct parent. For submodules of submodules, the scheme is  and the names of submodules of a given module must  be unique.

Diagramming the dependencies between program units
The following diagram shows the use and host association relationships between the modules (blue boxes), the submodule (green box), and a main program unit (orange box) for this example:

The small triangles in the diagram refer to use ("u") association and host ("h") association, respectively. The separation of the constructor's interface from its implementation leads to avoidance of circular  references (the lower two "u" triangles in the diagram).

The compilation order for separate files would be:


 * 1)   and , independently
 * 1)   and , independently

A type definition for invocation of a general function
In scientific applications, a commonly occurring requirement is the need to evaluate functions that depend on additional parameters, apart from their real-valued argument. For example, an application might need the value of spherical Bessel function $$x \mapsto j_l(q \, x) $$ for independently specified integer values of $$l$$ and real values of $$q$$. More generally, one can consider a real-valued mapping

$$\Re \ni x \mapsto f_\lambda(x) \quad (\lambda \in \Omega)$$,

where the parameter value $$\lambda$$ can be from some arbitrary set. This section presents a way for handling this programmatically, using the object-oriented features of Fortran. We start with the outline for a type definition of sufficient generality: It supplies


 * a procedure pointer component with an abstract interface that reflects the above mapping;
 * an unlimited polymorphic parameter component, to keep all things in one place.

Notionally, one could invoke a properly set up  object through Use of a procedure pointer reflects the fact that each   object will want to associate its individual target function; this is sometimes also referred to as an object-bound procedure. The  attribute in the type definition is needed because otherwise (analogous to what we saw for the earlier type-bound procedure examples), the object through which the invocation  is done would be obliged to appear as a first argument in the abstract interface  ; this would constitute an additional imposition on the implementation of the supplied functions. On the other hand, the invocation needs to explicitly specify the  component, making it a bit unwieldy; the use of   objects will be simplified as we go on.

Performance issues arising from object-oriented programming
Let us look at a target function implementation, in form of a trivial example $$\sin(\lambda x)$$: Given that an application is likely to request a large number of function values, the following effects would ensue once for each invocation:


 * function call overhead, and
 * overhead of run-time type resolution.

The resulting performance impact is typical for object-oriented designs that operate in multitudes on small objects. Making use of an array-based version of the function is desirable, since the overheads specified above only arise once, and the actual calculational code (marked "kernel" in the above box) is amenable to array-related compiler optimizations (the specifics of which depend on both hardware architecture and working set size).

Completing the function type definition
The aim now is to proceed to a framework that permits to use both the scalar and the array versions in a uniform way, thereby making life for the clients that use the framework easy, while enabling performance where it is needed.

The full definition of, including its referenced abstract interfaces, reads Because we now have two procedure pointers in the type (only one of which is used in each given object), it is advantageous to provide a generic type-bound procedure   as a front end for ease of use. The specifics  and   for this read The only way to invoke one of these (in a use association context) is via the generic name, since the specific type-bound procedures have the   attribute; note that   is not designed for being extended. Disambiguation is by rank of.

The structure constructor for the type is overloaded with the following specific functions: Disambiguation is possible due to the sufficiently different interfaces of the procedure arguments.

Using the function type
With the already-shown implementations for the target functions  and , using this framework is illustrated by the following: Omitting a   in a constructor is fine, as long as the target functions cater for the dummy argument's  non-presence.

The framework's implementation makes use of the fact that an unallocated actual argument associated with an  dummy argument is considered not present. Once conditional expressions are implemented in compilers, the code will be appropriately reworked, since use of this feature is recommended against.

Arrays of structures versus structures of arrays
Returning to our earlier example type body, the next idea would be to simulate the dynamics of a large ensemble of bodies. A procedure might be supplied that modifies the components of all ensemble members, for example as follows:



where  results from evaluating   at the position of the ensemble member.

Variations on the passed object
All examples for type-bound procedures given up to now have the property that the invoking object itself is passed as the first argument to the bound procedure. However, this default behaviour can be modified by the programmer


 * either declaring the binding with a  attribute that references the specific (and of course appropriately declared) procedure argument the object of the bound type should be passed to,
 * or declaring the binding with a  attribute, in which case the object is not (implicitly) passed to the procedure at all in a TBP invocation.

UDDTIO as generic type-bound procedures

procedure pointers

private vs. public TBPs and Generics

Parameterized derived types
Performance considerations

TBD sim