- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Using Release 7 of version 12.1, I'm trying to define a generic assignment function for a polymorphic variable. The following code demonstrates a couple of problems I'm having:
!=====================================================
module a_module
implicit none
private
public :: a_t
type a_t
contains
procedure, public :: assign
generic :: assignment(=) => assign
end type a_t
contains
subroutine assign(to, from)
class(a_t), intent(inout) :: to
class(a_t), intent(in) :: from
end subroutine assign
end module a_module
module b_module
use a_module
implicit none
private
public :: b_t
type, extends(a_t) :: b_t
contains
procedure, public :: assign
generic :: assignment(=) => assign
end type a_t
contains
subroutine assign(to, from)
class(b_t), intent(inout) :: to
class(b_t), intent(in) :: from
end subroutine assign
end module b_module
program main
use a_module
use b_module
implicit none
class(a_t), allocatable :: v1
class(a_t), allocatable :: v2
allocate(b_t::v1)
allocate(b_t::v2)
v2 = v1
end program
!=====================================================
The code as-is does not compile, giving me an error 8383. Shouldn't the code work as written?
If I change the name of the "assign" subroutine in b_module to something else (say, "assignb"), the code compiles and runs. However, when it reaches the statement "v2 = v1", it executes the subroutine assign in a_module. I would expect it to execute assignb in b_module. Is this behavior expected?
Thanks,
Doug
!=====================================================
module a_module
implicit none
private
public :: a_t
type a_t
contains
procedure, public :: assign
generic :: assignment(=) => assign
end type a_t
contains
subroutine assign(to, from)
class(a_t), intent(inout) :: to
class(a_t), intent(in) :: from
end subroutine assign
end module a_module
module b_module
use a_module
implicit none
private
public :: b_t
type, extends(a_t) :: b_t
contains
procedure, public :: assign
generic :: assignment(=) => assign
end type a_t
contains
subroutine assign(to, from)
class(b_t), intent(inout) :: to
class(b_t), intent(in) :: from
end subroutine assign
end module b_module
program main
use a_module
use b_module
implicit none
class(a_t), allocatable :: v1
class(a_t), allocatable :: v2
allocate(b_t::v1)
allocate(b_t::v2)
v2 = v1
end program
!=====================================================
The code as-is does not compile, giving me an error 8383. Shouldn't the code work as written?
If I change the name of the "assign" subroutine in b_module to something else (say, "assignb"), the code compiles and runs. However, when it reaches the statement "v2 = v1", it executes the subroutine assign in a_module. I would expect it to execute assignb in b_module. Is this behavior expected?
Thanks,
Doug
Link Copied
5 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can reproduce this - once I correct the typo in the declaration of b_t. The second problem, where it calls the a_t assignment, is I think one I've seen before, though I thought we had fixed it. I will check. I need to study the standard a bit before I comment on the first problem (error 8383).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
I found the error in what I sent you earlier. Consider the following:
!=====================================================
module a_module
implicit none
private
public :: a_t
type a_t
contains
procedure, public :: assign
generic :: assignment(=) => assign
end type a_t
contains
subroutine assign(to, from)
class(a_t), intent(inout) :: to
class(a_t), intent(in) :: from
end subroutine assign
end module a_module
module b_module
use a_module
implicit none
private
public :: b_t
type, extends(a_t) :: b_t
contains
procedure, public :: assign
end type b_t
contains
subroutine assign(to, from)
class(b_t), intent(inout) :: to
class(a_t), intent(in) :: from ! Previous error: needs to be of the same type as the overridden procedure
end subroutine assign
end module b_module
program main
use a_module
use b_module
implicit none
class(a_t), allocatable :: v1
class(a_t), allocatable :: v2
allocate(b_t::v1)
allocate(b_t::v2)
call v2%assign(v1)
v2 = v1
end program
!=====================================================
As per the comment, the "from" dummy argument needs to be of the same type as the overridden procedure.
The code now compiles, but the resulting performance doesn't seem to be correct. I would expect that the two lines "call v2%assign(v1)" and "v2 = v1" would execute the same procedure (the b_t type-bound procedure "assign"). The first line does this; the second executes the a_t "assign" function.
I found the error in what I sent you earlier. Consider the following:
!=====================================================
module a_module
implicit none
private
public :: a_t
type a_t
contains
procedure, public :: assign
generic :: assignment(=) => assign
end type a_t
contains
subroutine assign(to, from)
class(a_t), intent(inout) :: to
class(a_t), intent(in) :: from
end subroutine assign
end module a_module
module b_module
use a_module
implicit none
private
public :: b_t
type, extends(a_t) :: b_t
contains
procedure, public :: assign
end type b_t
contains
subroutine assign(to, from)
class(b_t), intent(inout) :: to
class(a_t), intent(in) :: from ! Previous error: needs to be of the same type as the overridden procedure
end subroutine assign
end module b_module
program main
use a_module
use b_module
implicit none
class(a_t), allocatable :: v1
class(a_t), allocatable :: v2
allocate(b_t::v1)
allocate(b_t::v2)
call v2%assign(v1)
v2 = v1
end program
!=====================================================
As per the comment, the "from" dummy argument needs to be of the same type as the overridden procedure.
The code now compiles, but the resulting performance doesn't seem to be correct. I would expect that the two lines "call v2%assign(v1)" and "v2 = v1" would execute the same procedure (the b_t type-bound procedure "assign"). The first line does this; the second executes the a_t "assign" function.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, I see this behavior. We'll look into it and get back to you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry for the delay - I have escalated this as issue DPD200175845. The compiler is using the "declared type" of v1 and v2 rather than the dynamic type.
I believe the error message for the original code is correct, since you give the routines the same name. Here is a modified version of the code which shows how this sort of thing is supposed to be done, though it still doesn't do what is wanted.
I believe the error message for the original code is correct, since you give the routines the same name. Here is a modified version of the code which shows how this sort of thing is supposed to be done, though it still doesn't do what is wanted.
[fortran]module a_module implicit none private public :: a_t type a_t contains procedure, public :: assign_a generic :: assignment(=) => assign_a end type a_t contains subroutine assign_a(to, from) class(a_t), intent(inout) :: to class(a_t), intent(in) :: from print *, "In assign_a" end subroutine assign_a end module a_module module b_module use a_module implicit none private public :: b_t type, extends(a_t) :: b_t contains procedure, public :: assign_b generic :: assignment(=) => assign_b end type b_t contains subroutine assign_b(to, from) class(b_t), intent(inout) :: to class(b_t), intent(in) :: from print *, "In assign_b" end subroutine assign_b end module b_module program main use a_module use b_module implicit none class(a_t), allocatable :: v1 class(a_t), allocatable :: v2 allocate(b_t::v1) allocate(b_t::v2) v2 = v1 end program [/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve. I have a similar question (see: http://software.intel.com/en-us/forums/topic/328732#comment-1681634) I see that the dereferencing of assignment based on declared type is standard-conforming. But is there another way of implementing a generic container which would be able to add values to storage from the declared class or any of its subclasses?
Thanks
Evgeniy

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page