- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module mod1
type, abstract :: tp1
contains
private
procedure(Isub1), pass, deferred :: sub1
end type tp1
abstract interface
subroutine Isub1(this)
import tp1
class(tp1) :: this
end subroutine Isub1
end interface
end module mod1
module mod2
use mod1
type, abstract, extends(tp1) :: tp2
contains
private
generic, public :: sub => sub1,&
sub2
procedure(Isub1), pass, deferred :: sub1
procedure(Isub2), nopass, deferred :: sub2
end type tp2
abstract interface
subroutine Isub2(a)
integer :: a
end subroutine Isub2
end interface
end module mod2
In the nested abstract types, interface Isub1 is inherited from tp1 but the compiler generates an error message of :
error #8262: For a type-bound procedure that has the PASS binding attribute, the first dummy argument must have the same declared type as the type being defined.
The error is clear, tp2 needs the first passed dummy argument to be of type tp2(or class tp2) but the inherited interface Isub1 declares the argument to be of type tp1(class tp1). So How should I design the abstract type tp1 to make it work ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module some_module
implicit none
type, abstract :: level0
contains
procedure(l0_jump), deferred :: jump
procedure(l0_skip), deferred :: skip
procedure(l0_hop), deferred :: hop
! Some generics that stick the above specifics behind a common
! name.
generic :: elevate => jump, skip, hop
generic :: exercise => jump, skip, hop
end type level0
! All these take a second scalar argument that differs in type,
! so that they can be part of the same generic.
abstract interface
subroutine l0_jump(arg, i)
import :: level0
implicit none
class(level0), intent(inout) :: arg
integer, intent(in) :: i
end subroutine l0_jump
subroutine l0_skip(arg, r)
import :: level0
implicit none
class(level0), intent(inout) :: arg
real, intent(in) :: r
end subroutine l0_skip
subroutine l0_hop(arg, l)
import :: level0
implicit none
class(level0), intent(inout) :: arg
logical, intent(in) :: l
end subroutine l0_hop
end interface
type, abstract, extends(level0) :: level1
contains
! We inherit jump, skip, hop specifics, and the exercise and
! elevate generics.
! Some specific bindings, specific to extensions of level1
! (where the terminology is such that "extension of x" includes
! x itself).
procedure(l1_walk), deferred :: walk
procedure(l1_jog), deferred :: jog
procedure(l1_run), deferred :: run
! A generic binding, only for extensions of level1 and, in this case,
! only using specifics from level1.
generic :: relocate => walk, jog, run
! Adds some specific bindings to the generic that
! was established in level1. These additional
! specifics are only considered when the
! declared type is an extension of level1
generic :: exercise => walk, jog, run
! Another generic, specific to extensions of level1, that has
! a mix of specifics from level0 and level1
generic :: warm_up => skip, jog
end type level1
! All these take a second rank one array argument that
! differs in type - so they can be part of the same generic
! and can be part of the same generic as in the level0 type
! (because those specifics took scalars).
abstract interface
subroutine l1_walk(arg, i)
import :: level1
implicit none
class(level1), intent(inout) :: arg
integer, intent(in) :: i(:)
end subroutine l1_walk
subroutine l1_jog(arg, r)
import :: level1
implicit none
class(level1), intent(inout) :: arg
real, intent(in) :: r(:)
end subroutine l1_jog
subroutine l1_run(arg, l)
import :: level1
implicit none
class(level1), intent(inout) :: arg
logical, intent(in) :: l(:)
end subroutine l1_run
end interface
type, extends(level1) :: level2
! ---> Some data entities.
contains
! Implementation of all the deferred bindings that we've
! picked up from our parents.
procedure :: jump => l2_jump
procedure :: skip => l2_skip
procedure :: hop => l2_hop
procedure :: walk => l2_walk
procedure :: jog => l2_jog
procedure :: run => l2_run
end type level2
contains
subroutine l2_jump(arg, i)
class(level2), intent(inout) :: arg
integer, intent(in) :: i
end subroutine l2_jump
subroutine l2_skip(arg, r)
class(level2), intent(inout) :: arg
real, intent(in) :: r
end subroutine l2_skip
subroutine l2_hop(arg, l)
class(level2), intent(inout) :: arg
logical, intent(in) :: l
end subroutine l2_hop
subroutine l2_walk(arg, i)
class(level2), intent(inout) :: arg
integer, intent(in) :: i(:)
end subroutine l2_walk
subroutine l2_jog(arg, r)
class(level2), intent(inout) :: arg
real, intent(in) :: r(:)
end subroutine l2_jog
subroutine l2_run(arg, l)
class(level2), intent(inout) :: arg
logical, intent(in) :: l(:)
end subroutine l2_run
end module some_module
All the bindings in the above are public by default. If they were private, then they would not be accessible outside of the module and could not be overridden.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just give the sub1 binding in tp2 a different name.
This was the topic of relatively recent interp material that the compiler may not have caught up with yet.
Because the tp1 type has a deferred binding that is private, it cannot be usefully used as a parent type outside of module mod1.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ianh wrote:
Just give the sub1 binding in tp2 a different name.
This was the topic of relatively recent interp material that the compiler may not have caught up with yet.
Because the tp1 type has a deferred binding that is private, it cannot be usefully used as a parent type outside of module mod1.
I changed sub1 to sub10 in tp2 but the compiler showed no difference and the error still exist. I tried using public attribute on sub1 in tp1 but resulted error as well. So are you suggesting writing another interface other than Isub1 in tp2, IanH ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes .... with hindsight.
Testing here with 17.0 update one, the compiler appears to be doing the right thing as per the corrected/clarified standard. Originally I thought the repeat use of the same binding name for a different binding might be confusing it.
Could you please clarify what you are trying to do? Why do you have two, independent bindings, with the same name?
This will compile with 17.0.1, but note again that neither type can actually be usefully used. You can't override the sub1 binding in the tp1 type outside of the mod1 module, because that binding is private. Similarly for the sub1 (which is a different binding to the one inherited from tp1!) and sub2 bindings in the tp2 type, outside of the mod2 module.
If you make the sub1 binding in tp1 public, then it can be overridden, but then you need to change the name of the binding declared in sub2 to be something else, because otherwise it will conflict with that inherited and accessible binding. If you just want tp2 to inherit the same sub1 binding from tp1, then you don't explicitly declare it in tp2. You can't make a binding that is public in a parent type, private in an extension.
module mod1
implicit none
private ! hides the abstract interface.
type, abstract, public :: tp1
contains
private
procedure(Isub1), pass, deferred :: sub1
end type tp1
abstract interface
subroutine Isub1(this)
import tp1
implicit none
class(tp1) :: this
end subroutine Isub1
end interface
end module mod1
module mod2
use mod1
implicit none
type, abstract, extends(tp1) :: tp2
contains
private
generic, public :: sub => sub1,&
sub2
procedure(Isub1), pass, deferred :: sub1
procedure(Isub2), nopass, deferred :: sub2
end type tp2
abstract interface
subroutine Isub1(this)
import tp2
implicit none
class(tp2) :: this
end subroutine Isub1
subroutine Isub2(a)
implicit none
integer :: a
end subroutine Isub2
end interface
end module mod2
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
type, abstract :: level0
contains
! ---> Some most basic methods (assume 3 funcs) waiting to be implemented, deferred.
end type level0
type, bastract, extends(level0) :: level1
contains
! ---> Some basic methods (assume another 3 funcs not associated of any kind with previous) to improve functionality, deferred as well.
end type level1
type, extends(level1) :: level2
! ---> Some data entities.
contains
! ----> Impementations of all the abstract methods (here we have 6 funcs), other functionalities may be add here too.
end type level2
I am looking forward to implement a three-level type structure. level0 is the base, level1 is higher than level0 and level2 is higher than level1. level0 and level1 are both abstract and level2 is the implementation. It works all right until GENERIC binding is used. How shall I resolve it ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
module some_module
implicit none
type, abstract :: level0
contains
procedure(l0_jump), deferred :: jump
procedure(l0_skip), deferred :: skip
procedure(l0_hop), deferred :: hop
! Some generics that stick the above specifics behind a common
! name.
generic :: elevate => jump, skip, hop
generic :: exercise => jump, skip, hop
end type level0
! All these take a second scalar argument that differs in type,
! so that they can be part of the same generic.
abstract interface
subroutine l0_jump(arg, i)
import :: level0
implicit none
class(level0), intent(inout) :: arg
integer, intent(in) :: i
end subroutine l0_jump
subroutine l0_skip(arg, r)
import :: level0
implicit none
class(level0), intent(inout) :: arg
real, intent(in) :: r
end subroutine l0_skip
subroutine l0_hop(arg, l)
import :: level0
implicit none
class(level0), intent(inout) :: arg
logical, intent(in) :: l
end subroutine l0_hop
end interface
type, abstract, extends(level0) :: level1
contains
! We inherit jump, skip, hop specifics, and the exercise and
! elevate generics.
! Some specific bindings, specific to extensions of level1
! (where the terminology is such that "extension of x" includes
! x itself).
procedure(l1_walk), deferred :: walk
procedure(l1_jog), deferred :: jog
procedure(l1_run), deferred :: run
! A generic binding, only for extensions of level1 and, in this case,
! only using specifics from level1.
generic :: relocate => walk, jog, run
! Adds some specific bindings to the generic that
! was established in level1. These additional
! specifics are only considered when the
! declared type is an extension of level1
generic :: exercise => walk, jog, run
! Another generic, specific to extensions of level1, that has
! a mix of specifics from level0 and level1
generic :: warm_up => skip, jog
end type level1
! All these take a second rank one array argument that
! differs in type - so they can be part of the same generic
! and can be part of the same generic as in the level0 type
! (because those specifics took scalars).
abstract interface
subroutine l1_walk(arg, i)
import :: level1
implicit none
class(level1), intent(inout) :: arg
integer, intent(in) :: i(:)
end subroutine l1_walk
subroutine l1_jog(arg, r)
import :: level1
implicit none
class(level1), intent(inout) :: arg
real, intent(in) :: r(:)
end subroutine l1_jog
subroutine l1_run(arg, l)
import :: level1
implicit none
class(level1), intent(inout) :: arg
logical, intent(in) :: l(:)
end subroutine l1_run
end interface
type, extends(level1) :: level2
! ---> Some data entities.
contains
! Implementation of all the deferred bindings that we've
! picked up from our parents.
procedure :: jump => l2_jump
procedure :: skip => l2_skip
procedure :: hop => l2_hop
procedure :: walk => l2_walk
procedure :: jog => l2_jog
procedure :: run => l2_run
end type level2
contains
subroutine l2_jump(arg, i)
class(level2), intent(inout) :: arg
integer, intent(in) :: i
end subroutine l2_jump
subroutine l2_skip(arg, r)
class(level2), intent(inout) :: arg
real, intent(in) :: r
end subroutine l2_skip
subroutine l2_hop(arg, l)
class(level2), intent(inout) :: arg
logical, intent(in) :: l
end subroutine l2_hop
subroutine l2_walk(arg, i)
class(level2), intent(inout) :: arg
integer, intent(in) :: i(:)
end subroutine l2_walk
subroutine l2_jog(arg, r)
class(level2), intent(inout) :: arg
real, intent(in) :: r(:)
end subroutine l2_jog
subroutine l2_run(arg, l)
class(level2), intent(inout) :: arg
logical, intent(in) :: l(:)
end subroutine l2_run
end module some_module
All the bindings in the above are public by default. If they were private, then they would not be accessible outside of the module and could not be overridden.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks a lot, IanH, that's just what I meant to do. Unfortunately there seems still something wrong with the warm_up generic in level1, the compiler generates :
------ Build started: Project: Test, Configuration: Debug|Win32 ------ Compiling with Intel(R) Visual Fortran Compiler 17.0.1.143 [IA-32]... Test.f90 D:\Project\Test\Test.f90(1560): error #8423: In GENERIC type bound procedure definition each binding name must be the name of a specific binding of the type. [SKIP] compilation aborted for D:\Project\Test\Test.f90 (code 1) Build log written to "file://D:\Project\Test\Debug\BuildLog.htm" Test - 2 error(s), 0 warning(s) ---------------------- Done ----------------------
I don't see any mistakes within the code so I am confusing too.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
(I corrected some spelling mistakes in the original post, and provided implementations of the l2_xxx procedures.)
I think that error is a compiler bug. skip is inherited and accessible from level0 - it is a binding of the type.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, this is a bug already being investigated. Issue ID is DPD200256336.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So just hope it'll be fixed in next release.
- 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
Steve Lionel (Intel) wrote:
Yes, this is a bug already being investigated. Issue ID is DPD200256336.
So is there a list I can refer to that whether the second update has had this issue fixed then?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Unfortunately, not at the present time. One of the Intel folks (I retired at the end of last year) can look up the issue and tell you the status.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This issue has not been fixed yet.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page