`generic :: write(formatted)`groutran中的子程序被其他派生类型调用

Ema*_*ssi 5 generics fortran gfortran

我正在使用几种派生类型.出于调试目的,我想通过使用一个很好的方式在屏幕上打印它们generic :: write(formatted).

这是一个显示我的意思的示例程序:

program main
  use :: test_mod
  implicit none

  type(test1) :: t1
  type(test2) :: t2

  t1 = test1(name="t1")
  t2 = test2(name="t2", t1)
  print *, 'Test1:', t1
  print *, 'Test2:', t2
end program
Run Code Online (Sandbox Code Playgroud)

这是模块:

module test_mod
  implicit none
  private
  public :: test1, test2

  type :: test1
    character(2) :: name
  contains
    procedure, private :: test1_writef
    generic :: write(formatted) => test1_writef
  end type test1

  type :: test2
    character(2) :: name
    type(test1) :: t1
  contains
    procedure, private :: test2_writef
    generic :: write(formatted) => test2_writef
  end type test2

contains

  subroutine test1_writef(self, unit, iotype, v_list, iostat, iomsg)
    class(test1), intent(in)    :: self      ! 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, "(a)", IOSTAT=iostat, IOMSG=iomsg) self%name
  end subroutine test1_writef

  subroutine test2_writef(self, unit, iotype, v_list, iostat, iomsg)
    class(test2), intent(in)    :: self      ! 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, "(a, ' <', a, '>')", IOSTAT=iostat, IOMSG=iomsg) self%name, self%t1
  end subroutine test2_writef

end module test_mod
Run Code Online (Sandbox Code Playgroud)

运行这个程序我希望得到:

Test1: t1
Test2: t2 <t1>
Run Code Online (Sandbox Code Playgroud)

但相反,我得到了gfortran:

Test1: t1
Test2: t2 <>
Run Code Online (Sandbox Code Playgroud)

"t1"字符串未写入屏幕.

我正在使用这个版本的gfortran:

[egissi@shibax ~]$ gfortran --version
GNU Fortran (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)

我知道我可以只更换self%t1self%t1%name,但我的类型是比这更复杂,我会更好地不重复同样的格式,其他派生类型.

我错过了什么?我怎样才能获得这种行为?

fra*_*lus 4

对于要使用的已定义输出过程,必须以某种方式“选择”它。在列表定向输出中

print *, 'Test1:', t1
print *, 'Test2:', t2
Run Code Online (Sandbox Code Playgroud)

程序test1_writeftest2_writef适用于有效项目t1t2。因此使用它们。

然而,对于子输出

write (unit, "(a, ' <', a, '>')", IOSTAT=iostat, IOMSG=iomsg) self%name, self%t1
Run Code Online (Sandbox Code Playgroud)

我们现在有一个明确的格式("(a,' <',a,'>')")。这里有效项目self%nameself%t1被明确编辑为字符。self%t1要请求处理对象,test1_writef必须显式使用dt编辑描述符:

write (unit, "(a, ' <', dt, '>')", IOSTAT=iostat, IOMSG=iomsg) self%name, self%t1
Run Code Online (Sandbox Code Playgroud)