- 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