Based on information found here and in the book Modern Fortran Explained (Incorporating Fortran 2018) by Metcalf, Reid, and Cohen (see section 11.6), I would expect to be able to customise the output of a derived type using an interface write(formatted)
block. However, while no compilation errors occur, the interface seems to be ignored.
A self-contained MWE would be:
module foo
type range
integer :: lower, upper
end type
interface write(formatted)
module procedure formatted_io_range
end interface
private
public formatted_io_range, range
contains
subroutine formatted_io_range(value, unit, iotype, vlist, iostat, iomsg)
class(range), intent(in) :: value
integer, intent(in) :: unit
character(len=*), intent(in) :: iotype
integer, dimension(:), intent(in) :: vlist
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
write (unit, "('range ',a,': ',i0,',',i0,*(i0))", iostat=iostat, iomsg=iomsg) iotype, value%lower, value%upper, vlist
end subroutine
end
program main
use foo
type(range) :: r
r = range(1, 2)
print *, r
write (*, *) r
print "(dt)", r
write (*, "(dt)") r
end
I would expect the output of this program to be
range LISTDIRECTED: 1,2
range LISTDIRECTED: 1,2
range DT: 1,2
range DT: 1,2
but compiling with
gfortran -Wall -Wextra -Wpedantic --std=f2018 -Og -fcheck=all foo.f90
and running what I get instead is:
1 2
1 2
At line 39 of file foo.f90 (unit = 6, file = 'stdout')
Fortran runtime error: Missing DTIO procedure or intrinsic type passed for item 1 in formatted transfer
(dt)
^
Error termination. Backtrace:
#0 0x101111bcf
#1 0x101112777
#2 0x101113047
#3 0x1011f932b
#4 0x10120822f
#5 0x10120833b
#6 0x100f63907
#7 0x100f63c7b
I can get the expected output by replacing the type definition with
type range
integer :: lower, upper
contains
procedure :: formatted_io_range
generic :: write(formatted) => formatted_io_range
end type
but then the interface write(formatted)
block isn't needed at all.
Is it possible to use the interface, or is the information in these resources incorrect (or have I misunderstood them)?
Follow up question: both resources say that you can use type(range)
instead of class(range)
in the formatting routine, but if I try that I get a compilation error:
foo.f90:14:39:
14 | subroutine formatted_io_range(value, unit, iotype, vlist, iostat, iomsg)
| 1
Error: DTIO dummy argument at (1) must be of type CLASS
Again, am I doing something wrong or have I misunderstood something?