From: Richard Maine on
B�lint Aradi <aradi(a)bccms.uni-bremen.de> wrote:

> The problem with your solution is that it uses inheritance. As F03
> only enables single inheritance and the language does not offer any
> alternative options (e.g. as interfaces in Java), your type to be
> sorted must be a child of sortType. However, what happens if
> myDataType is a pretty complex type, and was created by extending a
> type called myDataParent? And let's assume, myDataParent is defined
> somewhere else in the code, and you are not allowed/able to change its
> definition. Then, you don't have the possibility to make it a child of
> sortType, and therefore it can't be sorted,

You can, however, make a type myDataSortType, which extends sortType and
has a component of type myDataType. If I have my terminology straight,
this would be using imbedding. While one might argue that this
introduces a slight extra complication, it is *HUGELY* simpler than the
complications of multiple inheritance.

The omission of multiple inheritance was considered and deliberate.

> There are many realistic example, where in scientific code multiple
> inheritance (or Java-like interfaces) would be required.

I disagree, unless one has a strange definition of "required".
Substitute "could be used" instead of "required" and the statement is
more defensible, but then one needs to evaluate the cost-benefit
tradeoffs. The costs of multiple inheritance would have been huge.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
From: James Van Buskirk on
"B�lint Aradi" <aradi(a)bccms.uni-bremen.de> wrote in message
news:5ce6b402-656e-4215-8107-02b597b4f5bd(a)d77g2000hsb.googlegroups.com...

> There are many realistic example, where in scientific code multiple
> inheritance (or Java-like interfaces) would be required. For the case
> above templates could be alternative solution, but if you already know
> at compile time, what do you want to sort. However, if that depends on
> some external parameters (user input), it won't work either.

You can decide at run time how you want to sort by redefining your
comparison operator:

C:\gfortran\test\cray_overload>type cray_overload.f90
module mytype_mod
implicit none

type mytype
integer ikey
real rkey
end type mytype

interface operator(<)
pure function less_than(x,y)
import mytype
type(mytype), intent(in) :: x
type(mytype), intent(in) :: y
logical less_than
end function less_than
end interface operator(<)
pointer (p_lt, less_than)

contains
pure function compare_int(x,y)
type(mytype), intent(in) :: x
type(mytype), intent(in) :: y
logical compare_int

compare_int = x%ikey < y%ikey
end function compare_int

pure function compare_real(x,y)
type(mytype), intent(in) :: x
type(mytype), intent(in) :: y
logical compare_real

compare_real = x%rkey < y%rkey
end function compare_real
end module mytype_mod

program test
use mytype_mod
implicit none
type(mytype) A
type(mytype) B

A = mytype(3, 7.0)
B = mytype(5, 2.0)
p_lt = loc(compare_int)
call sub(A,B)
p_lt = loc(compare_real)
call sub(A,B)
end program test

subroutine sub(A, B)
use mytype_mod, only: mytype, operator(<)
implicit none
type(mytype) A
type(mytype) B

write(*,*) 'A = ', A
write(*,*) 'B = ', B
write(*,*) 'A < B = ', A < B
end subroutine sub

C:\gfortran\test\cray_overload>gfortran -fcray-pointer
cray_overload.f90 -ocray_
overload

C:\gfortran\test\cray_overload>cray_overload
A = 3 7.0000000
B = 5 2.0000000
A < B = T
A = 3 7.0000000
B = 5 2.0000000
A < B = F

C:\gfortran\test\cray_overload>ifort cray_overload.f90
Intel(R) Fortran Compiler for Intel(R) EM64T-based applications, Version 9.1
Build 20061104
Copyright (C) 1985-2006 Intel Corporation. All rights reserved.

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

-out:cray_overload.exe
-subsystem:console
cray_overload.obj

C:\gfortran\test\cray_overload>cray_overload
A = 3 7.000000
B = 5 2.000000
A < B = T
A = 3 7.000000
B = 5 2.000000
A < B = F

The above example uses cray pointers to achieve the operator
redefinition, but when f03 procedure pointers get implemented it
should be possible to produce a more portable version of my
example.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


From: Jim Xia on
Just repost what I said ...

> > Fortran has language features that C++ doesn't have that make
> > templates more awkward.  One of my favorites is that of having 3
> > different classes of expressions: ordinary expressions,
> > initialization expressions, and specification expressions.
> > Consider the following example, where template code is used for
> > 9 different instances: all 3 real KINDs times 3 different functions.
> > Since in f03 pretty much any intrinsic elemental function may take
> > part in an initialization epression, in our template code we must
> > be ready to handle named constants whose type is unknown to us as
> > we write the template code.  I don't see how to handle this in
> > the general case, but if the type is constrained to be numeric it
> > can be done!  Consider the following example:

Thanks for your reply. C++ also has many features that Fortran is
lacking. The dynamic initializations, for example, are also awkward
to simulate in Fortran if you ever want to try. I don't think
initialization expressions and specification expressions are big
issues here since C/C++ is using them as well -- they're not unique
to
Fortran. What unique to Fortran is the extent for these expressions
using intrinsic functions. C supports automatic variables that uses
specification expressions, and any constants you declare in C must be
defined using init-expr, and all static variables in C must also be
initialized with init-expr. Compiler does all the tricks to get all
the expressions (either init-expr or spec-expr) evaluated at the
right
time. I don't see how this can not be done too for templates.

What I'm interested at the moment is the function templates in
Fortran. By borrowing some of the C++ syntax, I hope I can explain
what I have in mind clearly. Say you want to define a generic
subroutine swap between two objects a and b, you can consider an
interface similar to the following:


template <S, T> subroutine swap (a, b)
type(S) a
type(T) b
!...
real :: local_array(a%kind * b%kind) !<-- should have no problem
for this declaration
!...
end subroutine


Both type S and T and their type parameters can be determined at the
call statement, such as


call swap (i, r)


If this subroutine is defined in a module, then I don't see much of a
technical issue for compiler to implement this. Again I maintain
that
only when there are enough demands.


In addition to above function templates, there is also a need for
template to complement the derived type with type parameters.
Currently the way F03 defines for kind type parameters for derived
types renders very little use for it by the type bound procedures.
It
is really awful to make a use of such a type. Consider the following
type


type counter (k)
integer, kind :: k
integer(k) :: count


contains


procedure :: increment
end type


...
Since the kind type parameters must be init-expr, there is no easy
way
to define a generic type bound subroutine increment for all kind
values. So if type parameter k can be 1, 2, 4 and 8, then you must
define 4 different increment routines to implement the same logic.
Here again the template is needed:


template <k> subroutine increment (c)
class(counter(k)), intent(inout) :: c


c%count = c%count + 1
end subroutine
...


The you can understand what I meant for the following code


type(counter(8)) c


...
call c%increment !<-- we know c%k is 8 at invocation
...


Hope this explains :-)


Cheers,


From: Jim Xia on
> You can, however, make a type myDataSortType, which extends sortType and
> has a component of type myDataType. If I have my terminology straight,
> this would be using imbedding.

This is called containment in OOP design.


> The omission of multiple inheritance was considered and deliberate.

I'm glad Fortran has chosen single inheritance. I think you can
resolve most issues, if not all of them, for the need of Java-like
interfaces by using containment relationship. Inheritance is not the
only way to solve the generic algorithm issues.

Cheers,

Jim