Suppose I have this simple class:
Module Foo
...
character(len=3), parameter :: describe_Foo=(/'BAR', 'BED', 'BOD'/)
...
type :: A
real :: value
integer :: descriptor
contains
procedure :: getter
procedure :: setter
...
end type A
contains
function writetype(self,...)
...
write(writetype,*) self%value, describe_foo(self%descriptor)
end function writetype
...
end module Foo
How can I define its interface to "write" so that every time this type is passed to the write statement it outputs the string defined by the class method writetype
.
In other words, in Python parlance, can I implement the equivalent of an __str__()
method?
I've found tantalizing tidbits suggesting that this is possible, see User-defined derived-type Input/Output procedures (Fortran 2003) and User-defined derived-type Input/Output procedure interfaces (Fortran 2003). These documents give ample information to write the methods I need, but it is still unclear to me how to define an interface or procedure specification so that the behavior I want occurs.
Example application:
program test
...
type(A) :: bartype, bedtype
...
bartype=A(120.0,1)
bedtype=A(102.0,2)
write(*,*) bartype,bedtype
end program test
Desired output:
>test.exe
120.0000 BAR
102.0000 BED
You need to have a generic WRITE(FORMATTED) binding, bound to a specific procedure that has suitable characteristics. See section 9.6.4.8 in the F2008 standard for more information.
type :: A
real :: value
integer :: descriptor
contains
procedure :: writetype
generic :: write(formatted) => writetype
end type A
...
subroutine writetype(dtv, unit, iotype, v_list, iostat, iomsg)
! Argument names here from the std, but you can name them differently.
class(A), intent(in) :: dtv ! Object to write.
integer, intent(in) :: unit ! Internal unit to write to.
character(*), intent(in) :: iotype ! LISTDIRECTED or DTxxx
integer, intent(in) :: v_list(:) ! parameters from fmt spec.
integer, intent(out) :: iostat ! non zero on error, etc.
character(*), intent(inout) :: iomsg ! define if iostat non zero.
...
write (unit, "(F9.4,1X,A)", IOSTAT=iostat, IOMSG=iomsg) &
dtv%value, describe_foo(dtv%descriptor)
end subroutine writetype
It is probably also worth noting that you need a compiler that implements this!