C/C++ and Fortran

 View Only

Object-Oriented Fortran: User-defined assignment bindings

By Archive User posted Thu September 08, 2011 12:14 PM


Originally posted by: Rafik_Zurob

Last week, I wrote about user-defined constructors in Fortran 2003. This week, I'd like to discuss user-defined assignment bindings and their role as "copy constructors" for allocatable components.

Like Fortran 90's user-defined assignment interface blocks, Fortran 2003's user-defined assignment bindings define a set of subroutines the compiler must call to perform assignment between objects of two types. User-defined assignment bindings are treated differently from interface blocks when you have intrinsic assignment between types containing allocatable components. Consider the following program which defines an assignment binding for copying objects of type dt1 and a defined assignment interface block for copying objects of type dt2:

module m
  implicit none
  type dt1
    integer :: data
    procedure assign_dt1
    generic :: assignment(=) => assign_dt1
  end type

  type dt2
    integer :: data
    procedure assign_dt2
  end type

  type container
    type(dt1), allocatable :: d1
    type(dt2), allocatable :: d2
  end type

  interface assignment(=)
    module procedure assign_dt2
  end interface
  subroutine assign_dt1(to, from)
    class(dt1), intent(out) :: to
    type(dt1), intent(in) :: from

    to%data = from%data + 10
  end subroutine

  subroutine assign_dt2(to, from)
    class(dt2), intent(out) :: to
    type(dt2), intent(in) :: from

    to%data = from%data + 10
  end subroutine
end module

use m
implicit none
type(container) c1, c2
allocate(c1%d1, source=dt1(3))
allocate(c1%d2, source=dt2(4))
c2 = c1
print *, c2%d1
print *, c2%d2

As done last week, I'll use the functrace feature of XLF to show what's going on:

> xlf2003 assignment_binding_example.f -qfunctrace tracing_routines.o
** m   === End of Compilation 1 ===
** _main   === End of Compilation 2 ===
1501-510  Compilation successful for file assignment_binding_example.f.
> a.out
{ _main (assignment_binding_example.f:43)
{ __m_NMOD_assign_dt1 (assignment_binding_example.f:29)
} __m_NMOD_assign_dt1 (assignment_binding_example.f:30)
} _main (assignment_binding_example.f:48)

In the intrinsic assignment between variables c1 and c2, the assignment binding was called for the derived type assignment of c1%d1 to c2%d1. This is not done for user-defined assignment interface blocks. As a result, subroutine assign_dt2 was not called in this program, and intrinsic assignment was used for the derived type assignment of c1%d2 to c2%d2.