Skip to content

Instantly share code, notes, and snippets.

@drikosev
Last active September 17, 2019 19:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drikosev/6fa28d8c9ba771d4e59b97f8f3bb4f89 to your computer and use it in GitHub Desktop.
Save drikosev/6fa28d8c9ba771d4e59b97f8f3bb4f89 to your computer and use it in GitHub Desktop.
module types
implicit none
type, public, abstract :: base_t
real*4 :: c(4)
contains
procedure :: className => baseClassName
procedure :: print => basePrint
procedure :: init => baseInit
end type base_t
interface assignment(=)
procedure :: assign_base_t !allocatable lhs
end interface assignment(=)
public :: assign_base_t
! Without this median based_t type, a sub-type
! can't access methods of the base_t type. Such
! a median type isn't required by PGI Fortran but
! other Fortran compilers agree that is required.
type, extends(base_t) :: based_t
end type based_t
private ::based_t
type, extends(based_t) :: p_t
contains
procedure :: className => pClassName
procedure :: init => pInit
end type p_t
interface p_t
module procedure :: new_p ! constructor of type(p_t)
end interface p_t
private :: p_t
PUBLIC :: new_p ! This constructor is public.
type, extends(based_t) :: v_t
contains
procedure :: className => vClassName
procedure :: init => vInit
end type v_t
interface v_t
module procedure :: new_v ! constructor of type(v_t)
end interface v_t
private v_t
PUBLIC :: new_v ! This constructor is public.
contains
type(p_t) function new_p()
new_p%c = [ 0.0 , 0.0, 0.0, 0.0 ]
call new_p%init() !Further initializations?
end function new_p
type(v_t) function new_v()
new_v%c = [ 0.0 , 0.0, 0.0, 1.0 ]
call new_v%init() !Further initializations?
end function new_v
subroutine baseInit(this)
class(base_t) , intent(inout) :: this
!print *, "(baseInit) ", this%className()
end subroutine baseInit
subroutine basePrint(this)
class(base_t) , intent(inout) :: this
print *, "(", this%className(), ") % c = ", this%c
end subroutine basePrint
! each class implements the className.
function baseClassName(this)
class(base_t) , intent(in) :: this
character(kind=1,len=:),allocatable :: baseClassName
baseClassName="base_t"
end function baseClassName
function vClassName(this)
class(v_t) , intent(in) :: this
character(kind=1,len=:),allocatable :: vClassName
vClassName="v_t"
end function vClassName
subroutine vInit(this)
class(v_t) , intent(inout) :: this
!call this%based_t%init()
!print *, "(vInit) ", this%className()
end subroutine vInit
function pClassName(this)
class(p_t) , intent(in) :: this
character(kind=1,len=:),allocatable :: pClassName
pClassName="p_t"
end function pClassName
subroutine pInit(this)
class(p_t) , intent(inout) :: this
!call this%based_t%init()
!print *, "(pInit) ", this%className()
end subroutine pInit
subroutine assign_base_t(to, from)
class(base_t), allocatable, intent(inout) :: to
class(base_t), intent(in) :: from
allocate(to,source=from) !copying is a weak point here
end subroutine
end module types
program init
use types
use, intrinsic :: iso_fortran_env, only : compiler_version
class(base_t), allocatable :: p,v
p=new_p()
v=new_v()
print *, "Compiler version: ", compiler_version()
call p % print()
call v % print()
end program init
$ gfortran types-module.f90 types.driver.f90 -o ginit4 && ./ginit4
Compiler version: GCC version 4.8.5
(p_t) % c = 0.00000000 0.00000000 0.00000000 0.00000000
(v_t) % c = 0.00000000 0.00000000 0.00000000 1.00000000
Sep 16, 2019
Ev. Drikos
The program in this gist demonstrates how one can achieve
default initialization on Fortran derived types, since the
language does not inherently support such a functionality.
In Specific, Fortran allows the instantiation of an object
that hasn't been initialized by any constructor. This code
attempts to force the instantiation of allocatable objects
that require references from our derived type constructors.
Profiling this program with Instruments (Version 9.3) does
not give me the impression that there are any memory leaks
other than those expected, ie from the WRITE REAL function,
usually reported when one loads a dynamic library (shlib).
Whatsover, these leaks are unrelated to object allocations.
Revisions
1. Uploaded to github.
2. PGI Fortran prefers a "private" specification statement,
instead of an access specification attribute in a derived
type definition statement, which should be equivalent.
3. Adjust the comment of the 2nd revision.
4. Move the module to a separate file and create this file
along with a printout with the program results.
Also, add an intermediate type that allows subclasses to
call specific methods of the abstract base type.
5. Delete the original file "init.f90"
6. Update the file "Types.Readme.txt" on github.
Files
1. The file "types-module.f90" contains the module "types".
2. The file "types.driver.f90" contains a main program that
uses the module "types".
3. The file "types.output.txt" contains the printout created
when I run this program on macOS 10.13 and the program had
been compiled by GNU Fortran version "4.8.5~36" for macOS,
built as documented at: https://github.com/drikosev/pc
4. The file "Types.Readme.txt" is the one you're reading now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment