- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I'm (still) trying to set procedure pointers in a derived type. I've been able to get it to work in simple examples (thanks to Steve) but as soon as I try somthing more complicated (the derived type now contains an allocatable array of another derived type) it will not compile. Here's example code:
[cpp]module foo_Mod implicit none ! Precision constants integer, parameter:: HI=selected_real_kind(12) integer, parameter:: LO=selected_real_kind(5) integer, parameter:: I_HI=selected_int_kind(9) integer, parameter:: I_LO=selected_int_kind(4) ! Define foo object type foo integer(kind=I_LO) :: foo_size character(len=1), dimension(:), allocatable :: foo_var end type foo ! Define fooFoo object type fooFoo integer(kind=I_LO) :: foo_len type(foo), dimension(:), allocatable :: foo_var procedure(parse_FooFunc), pointer, pass(base_fooFoo) :: getSubfoo end type fooFoo ! Define abstract interfaces for type-bound procedures abstract interface function parse_FooFunc(base_fooFoo,l_Bound,u_Bound) import type(fooFoo), intent(in) :: base_fooFoo integer(kind=I_LO), intent(in) :: l_Bound, u_Bound type(fooFoo) :: parse_FooFunc end function parse_FooFunc end interface ! Define assignment interface interface assignment(=) module procedure set_foo module procedure set_fooFoo end interface ! Define generic interface for len function interface len module procedure get_Size module procedure get_Length end interface contains function new_foo(foo_len,foo_var) result(newFoo) implicit none character(len=1), dimension(:), intent(in), optional :: foo_var integer(kind=I_LO), intent(in), optional :: foo_len type(foo) :: newFoo integer(kind=I_LO) :: fooLen logical :: alloc_Flag ! See if optional arguements are present if (present(foo_len)) then fooLen = foo_len else fooLen = 0 end if alloc_Flag = .False. if (present(foo_var)) then alloc_Flag = .True. end if ! Construct new foo object newFoo%foo_size = fooLen if (alloc_Flag) then allocate(newFoo%foo_var(len(foo_var))) newFoo%foo_var = foo_var end if return end function new_foo pure subroutine set_foo(base_foo,new_fooVar) implicit none type(foo), intent(inout) :: base_foo character(len=*), intent(in) :: new_fooVar integer(kind=I_LO) :: kount, new_Size logical :: alloc_Flag, assoc_Flag ! Get length of new foo_var new_Size = len(new_fooVar) ! As this may be a redefinition of base_foo check allocation ! status and set alloc_Flag to true if foo_var must be allocated alloc_Flag = .not. allocated(base_foo%foo_var) ! Test that any allocation is appropriate if (.not. alloc_Flag) then ! foo_var has already been allocated, is it the right size alloc_Flag = len(base_foo) /= new_Size ! If foo_var has the wrong size, deallocate if (alloc_Flag) then deallocate(base_foo%foo_var) end if end if ! If necessary, resize and allocate storage array if (alloc_Flag) then base_foo%foo_size = new_Size allocate(base_foo%foo_var(new_Size)) end if ! Assign new foo_var to base foo object do kount = 1,len(base_foo) base_foo%foo_var(kount) = new_fooVar(kount:kount) end do return end subroutine set_foo pure function get_Size(base_foo) result(foo_Size) implicit none type(foo), intent(in) :: base_foo integer(kind=I_LO) :: foo_Size ! Extract foo_var size foo_Size = base_foo%foo_size end function get_Size function new_fooFoo(fooFoo_len,fooFoo_var) result(newFooFoo) implicit none type(foo), dimension(:), intent(in), optional :: fooFoo_var integer(kind=I_LO), intent(in), optional :: fooFoo_len type(fooFoo) :: newFooFoo integer(kind=I_LO) :: fooFooLen logical :: alloc_Flag ! See if optional arguements are present if (present(fooFoo_len)) then fooFooLen = fooFoo_len else fooFooLen = 0 end if alloc_Flag = .False. if (present(fooFoo_var)) then alloc_Flag = .True. end if ! Construct new foo object newFooFoo%foo_len = fooFooLen if (alloc_Flag) then allocate(newFooFoo%foo_var(size(fooFoo_var))) newFooFoo%foo_var = fooFoo_var end if ! Associate function pointers newFooFoo%getSubfoo => get_Subfoo return end function new_fooFoo pure subroutine set_fooFoo(base_fooFoo,foo_Foo) implicit none type(fooFoo), intent(inout) :: base_fooFoo type(foo), dimension(:), intent(in) :: foo_Foo integer(kind=I_LO) :: kount, new_fooLen logical :: alloc_Flag, assoc_Flag ! Get length of new fooFoo new_fooLen = size(foo_Foo) ! As this may be a redefinition of the fooFoo check allocation ! status and set alloc_Flag to true if foo_var must be allocated alloc_Flag = .not. allocated(base_fooFoo%foo_var) ! Test that any allocation is appropriate if (.not. alloc_Flag) then ! foo_var has already been allocated, is it the right size alloc_Flag = len(base_fooFoo) /= new_fooLen ! If string has the wrong size, deallocate if (alloc_Flag) then deallocate(base_fooFoo%foo_var) end if end if ! If necessary, resize and allocate storage array if (alloc_Flag) then base_fooFoo%foo_Len = new_fooLen allocate(base_fooFoo%foo_var(new_fooLen)) end if ! Assign new foo_var to base fooFoo object base_fooFoo%foo_var = foo_foo return end subroutine set_fooFoo pure function get_Length(base_fooFoo) result(foo_Len) implicit none type(fooFoo), intent(in) :: base_fooFoo integer(kind=I_LO) :: foo_Len ! Extract fooFoo length foo_Len = base_fooFoo%foo_Len end function get_Length function get_Subfoo(base_fooFoo,l_Bound,u_Bound) implicit none type(fooFoo), intent(in) :: base_fooFoo integer(kind=I_LO), intent(in) :: l_Bound, u_Bound type(fooFoo) :: get_Subfoo ! Create an allocatable object for work type(foo), dimension(:), allocatable :: work integer(kind=I_LO) :: kount, indx, N_lo, N_up logical :: range_Flag ! Make sure that bounds are appropriate ! No graceful exit - exception handling (can't print in pure routine) range_Flag = .True. if (l_Bound < 1 .or. l_Bound > len(base_fooFoo)) then ! l_Bound is not in range !stop 'get_Substring: Lower bound not in range.' range_Flag = .False. elseif (u_Bound < 1 .or. u_Bound > len(base_fooFoo)) then ! u_Bound is not in range !stop 'get_Substring: Upper bound not in range.' range_Flag = .False. elseif (u_Bound < l_Bound) then ! Upper bound is less than lower bound, print warning !write(*,*) '(Warning) get_Substring: Upper bound < Lower bound.' !write(*,*) 'Reversing order of bounds' N_lo = u_Bound N_up = l_Bound else ! Everything is fine, do straight mapping to loop parameters N_lo = l_Bound N_up = u_Bound end if ! If all is well with subfoo bounds, proceed if (range_Flag) then ! Allocate work space allocate(work(N_up-N_lo+1)) ! Loop over base_fooFoo's elements and extract the desired foos do kount = N_lo,N_up indx = kount - N_lo + 1 work(indx) = base_fooFoo%foo_var(kount) end do ! Spawn new fooFoo object associated with work array get_Subfoo = work end if return end function get_Subfoo end module foo_Mod[/cpp]
When I try to complile this, I get an error message #8178: The procedure pointer and the procedure target must have matching arguments. This is on the assignment:
[cpp]newFooFoo%getSubfoo => get_Subfoo [/cpp]
in the function new_fooFoo. Any ideas why the compiler thinks that the arguments don't match?
Thanks,
Rich
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe that this is our bug ID DPD200050116 which is being fixed for s future release. The problem occurs when you do a pointer assignment of a contained procedure. Since I think a lot of people will be doing this, I will ask that the fix be released as soon as possible.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe that this is our bug ID DPD200050116 which is being fixed for s future release. The problem occurs when you do a pointer assignment of a contained procedure. Since I think a lot of people will be doing this, I will ask that the fix be released as soon as possible.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe that this is our bug ID DPD200050116 which is being fixed for s future release. The problem occurs when you do a pointer assignment of a contained procedure. Since I think a lot of people will be doing this, I will ask that the fix be released as soon as possible.
Thanks Steve! I can stop banging my head on the desk now. I think that you're right, if you're going to support OO you've gotta support that, it's part of the data encapsulation paradigm. I also noticed that I can't hide the individual fields of a derived type. Will that be supported any time soon? Thanks again!
Rich
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Public components of a private type and private components of a public type? That's still some time away.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Public components of a private type and private components of a public type? That's still some time away.
Yup, though I'm interested more in the latter rather than the former.
Thanks,
Rich

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