Daniel Fridline wrote:
>
> A while ago, actually I think it was over 2 years ago, a thread
> concerning the coding of a so-called "Generic Linked List" in Fortran 90
> was started in this list. Unfortunately, the archives only go back to
> October 1997 and I think that most of the discussion was before that.
>
> It involved writing the list using a "generic" data type for the nodes and
> using the TRANSFER() function to create additional list types from the
> "generic" type. Someone, and I'm sorry that I forgot who did it, posted a
> fairly detailed bit of code for doing this.
>
> 1.) Does anyone remember this discussion?
> 2.) If so, does anyone have the original code that they can
> upload here?
> 3.) If not, does anyone have any other suggestion for creating a linked
> data structure in the "generic" sense?. Essentially, what I am looking
> for is a way to do C++ like templates in a Fortran90 way.
>
Yes, about two years ago, I have posted a way to create a generic
type. Included is the sample program.
The procedure is first to convert to a "neutral" type by using TRANSFER,
then do the list processing, and to bring back to the original type
variables again by using TRANSFER.
For each type, a set of wrapper function has to be written. Using
this method, a list of heterogeneous elements is even possible.
Regards,
Jean Vezina
module generic
implicit none
!
! The generic list
!
type :: generic_list
private
integer :: tag ! Tag
character(1),pointer:: element(:) ! Neutral data type
end type generic_list
!
! Print routines
!
interface print
module procedure print_internal,print_array
end interface
!
! Generic assignment
!
interface assignment(=)
module procedure ass_real,ass_charac,ass_integer
end interface
!
private :: ass_real,ass_charac,ass_integer,print_internal
private :: print_array
!
contains
!
! Specific routines to convert to the "neutral" type
!
subroutine ass_real(elem,tab)
implicit none
type (generic_list),intent(out):: elem
real ,intent(in)::tab(:)
call fit(elem,transfer(tab,(/"1"/)),1)
return
end subroutine ass_real
!
subroutine ass_integer(elem,tab)
implicit none
type (generic_list),intent(out):: elem
integer ,intent(in)::tab(:)
call fit(elem,transfer(tab,(/"1"/)),3)
return
end subroutine ass_integer
!
subroutine ass_charac(elem,tab)
implicit none
type (generic_list),intent(out):: elem
character(*) ,intent(in)::tab
call fit(elem,transfer(tab,(/"1"/)),2)
return
end subroutine ass_charac
!
subroutine fit(elem,arg,itype)
implicit none
type(generic_list),intent(out) :: elem
character(1),intent(in)::arg(:)
integer,intent(in)::itype
allocate(elem%element(size(arg)))
elem%element=arg
elem%tag=itype
return
end subroutine fit
!
subroutine print_internal(val)
implicit none
type(generic_list),intent(in) :: val
select case(val%tag)
case(1)
write(*,*) transfer(val%element,(/1.e0/))
case (2)
write(*,*) transfer(val%element,(/"1"/))
case(3)
write(*,*) transfer(val%element,(/1/))
end select
return
end subroutine print_internal
!
subroutine print_array(a)
implicit none
type (generic_list),intent(in)::a(:)
integer::j
do j=1,size(a)
call print_internal(a(j))
end do
return
end subroutine print_array
end module generic
!
!
! esempio:
!
program test
use generic
implicit none
integer:: j
real::f(8)=(/(j,j=1,8)/)
type (generic_list) :: a(10)
! The "dynamic type" array contains elements
! of various types
a(1)='123'
a(2)=(/23.,34./)
a(3)='1234567890'
a(4)=f+1
a(5)=(/0./)
a(6)='claudia'
a(7)=(/3.14/)
a(8)='d'
a(9)=(/12./)
a(10)=(/ 777 /)
! Generic print called
call print(a)
call print (a(5))
call print (a(5:4:-1))
stop
end program test
!
|