- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dong Zheng wrote:I'd like to add user defined derived-type IO for an extended type. However I got an error message
"error #8638: The type/rank signature for arguments of this specific subroutine is identical to another specific subroutine that shares the same defined I/O." Anyone has idea how to do this? ..
With your design with the derived type and its extension type in the same module and thus any considerations of PRIVATE/PUBLIC attributes being moot, you need to effectively employ the "override" feature in standard Fortran to point the specific binding in the extension type to its own implementation. The generic binding can be retained as-is.
type, extends(mydata_t) :: myint_t
integer :: nn
integer, pointer :: xx(:)
contains
! "override" write_unfmt_mydata with a specific procedure binding
! to myint_t
procedure :: write_unfmt_mydata => write_unfmt_myint
end type myint_t
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Abstract interfaces?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dong Zheng wrote:I'd like to add user defined derived-type IO for an extended type. However I got an error message
"error #8638: The type/rank signature for arguments of this specific subroutine is identical to another specific subroutine that shares the same defined I/O." Anyone has idea how to do this? ..
With your design with the derived type and its extension type in the same module and thus any considerations of PRIVATE/PUBLIC attributes being moot, you need to effectively employ the "override" feature in standard Fortran to point the specific binding in the extension type to its own implementation. The generic binding can be retained as-is.
type, extends(mydata_t) :: myint_t
integer :: nn
integer, pointer :: xx(:)
contains
! "override" write_unfmt_mydata with a specific procedure binding
! to myint_t
procedure :: write_unfmt_mydata => write_unfmt_myint
end type myint_t
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@FortranFan,
Thanks. This works.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Dong Zheng,
Please note if you wish to follow suggested good practices with object-oriented (OO) design that starts with "information hiding" but yet strive to have your Fortran derived types reflect and OO "class" in conjunction with Fortran standard facilities of having methods operate on a "class" and inherit and employ polymorphism in terms of Fortran type-bound procedures and their extension, then consider having each derived type in its own module, control information in terms of PRIVATE/PUBLIC attributes, adopt "names" of specific bindings via xx => yy option, etc. as shown below. I don't extend the concept to data encapsulated by the derived type but the same principles apply. Proceed carefully though because OO, like pointers, can give coders a long rope to tie themselves up in all kinds of knots if not handled carefully.
module mydata_m
implicit none
private
type, public :: mydata_t
character(len=10) :: name
contains
private
procedure, pass(dtv) :: write_unfmt => write_unfmt_mydata
generic, public :: write(unformatted) => write_unfmt
end type mydata_t
contains
subroutine write_unfmt_mydata(dtv, unit, iostat, iomsg)
class(mydata_t), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
write(unit, iostat=iostat, iomsg=iomsg) dtv%name
end subroutine write_unfmt_mydata
end module mydata_m
module myint_m
use mydata_m, only : mydata_t
implicit none
private
type, extends(mydata_t), public :: myint_t
integer :: nn
integer, pointer :: xx(:)
contains
private
procedure, pass(dtv) :: write_unfmt => write_unfmt_myint
end type myint_t
contains
subroutine write_unfmt_myint(dtv, unit, iostat, iomsg)
class(myint_t), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
write(unit, iostat=iostat, iomsg=iomsg) dtv%mydata_t
write(unit, iostat=iostat, iomsg=iomsg) dtv%nn
write(unit, iostat=iostat, iomsg=iomsg) dtv%xx(1:dtv%nn)
end subroutine write_unfmt_myint
end module myint_m
program test
use mydata_m, only : mydata_t
use myint_m, only : myint_t
implicit none
type(mydata_t) :: dd
type(myint_t) :: ii
dd = mydata_t( 'xyz' )
ii%name = 'abc'
ii%nn = 100
allocate(ii%xx(ii%nn))
ii%xx = 5
open(10, file='test.dat', form='unformatted')
write(10) dd
write(10) ii
end program test
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dong Zheng wrote:.. when I test the code you posted above. It compiled with no problem but did not work as expected. I add a print statement in both "write_unfmt_mydata" and "write_unfmt_myint" respectively. It shows that "write_unfmt_myint" is not used. ..
My hunch at present is this is a compiler bug in Intel Fortran. Note the output with gfortran is as I currently expect - see below. I'll check the standard further on this.
C:\Temp>type p.f90
module mydata_m
implicit none
private
type, public :: mydata_t
character(len=10) :: name
contains
private
procedure, pass(dtv) :: write_unfmt => write_unfmt_mydata
generic, public :: write(unformatted) => write_unfmt
end type mydata_t
contains
subroutine write_unfmt_mydata(dtv, unit, iostat, iomsg)
class(mydata_t), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
print *, 'in mydata'
write(unit, iostat=iostat, iomsg=iomsg) dtv%name
end subroutine write_unfmt_mydata
end module mydata_m
module myint_m
use mydata_m, only : mydata_t
implicit none
private
type, extends(mydata_t), public :: myint_t
integer :: nn
integer, pointer :: xx(:)
contains
private
procedure, pass(dtv) :: write_unfmt => write_unfmt_myint
end type myint_t
contains
subroutine write_unfmt_myint(dtv, unit, iostat, iomsg)
class(myint_t), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(len=*), intent(inout) :: iomsg
print *, 'in myint'
write(unit, iostat=iostat, iomsg=iomsg) dtv%mydata_t
write(unit, iostat=iostat, iomsg=iomsg) dtv%nn
write(unit, iostat=iostat, iomsg=iomsg) dtv%xx(1:dtv%nn)
end subroutine write_unfmt_myint
end module myint_m
program test
use, intrinsic :: iso_fortran_env, only : compiler_version
use mydata_m, only : mydata_t
use myint_m, only : myint_t
implicit none
type(mydata_t) :: dd
type(myint_t) :: ii
print *, "Compiler Version: ", compiler_version()
dd = mydata_t( 'xyz' )
ii%name = 'abc'
ii%nn = 100
allocate(ii%xx(ii%nn))
ii%xx = 5
open(10, file='test.dat', form='unformatted')
write(10) dd
write(10) ii
end program test
C:\Temp>gfortran -Wall -std=f2018 p.f90 -o p.exe
C:\Temp>p.exe
Compiler Version: GCC version 10.0.0 20190512 (experimental)
in mydata
in myint
in mydata
C:\Temp>
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page