Reputation: 6194
I would like to assign a pointer in a derived type that is contained in the same derived type. The code below gives me the error below. What is going on here, and how can I solve this?
24 | zoos(i)%tigers(1) => zoos(i)%animals(1, 1)
| 1
Error: Expected bounds specification for 'zoos' at (1)
module mo_zoo
implicit none
type zoo
integer, dimension(:,:), pointer :: animals
integer, dimension(:), pointer :: tigers
integer, dimension(:), pointer :: ducks
end type zoo
save
type(zoo), dimension(:), pointer :: zoos
end module mo_zoo
program test
use mo_zoo
implicit none
integer :: n_zoos
integer :: i
n_zoos = 4
allocate(zoos(n_zoos))
do i = 1, n_zoos
allocate(zoos(i)%animals(10, 2))
zoos(i)%tigers(1) => zoos(i)%animals(1, 1)
zoos(i)%ducks(1) => zoos(i)%animals(1, 2)
end do
end program test
Upvotes: 3
Views: 502
Reputation: 2981
The problem is nothing to do with the derived type, and the error message is wrong.
The problem is that zoos(i)%ducks
is a pointer to an array, not an array of pointers, so you need to point zoos(i)%ducks
at zoos(i)%animals(:, 2)
, rather than zoos(i)%ducks(1)
at zoos(i)%animals(1, 2)
.
I have previously talked about this in this answer.
I believe this does what you want:
module mo_zoo
implicit none
type zoo
integer, dimension(:,:), pointer :: animals
integer, dimension(:), pointer :: tigers
integer, dimension(:), pointer :: ducks
end type zoo
save
type(zoo), dimension(:), pointer :: zoos
end module mo_zoo
program test
use mo_zoo
implicit none
integer :: n_zoos
integer :: i
n_zoos = 4
allocate(zoos(n_zoos))
do i = 1, n_zoos
allocate(zoos(i)%animals(10, 2))
zoos(i)%tigers => zoos(i)%animals(:, 1)
zoos(i)%ducks => zoos(i)%animals(:, 2)
end do
end program test
I would also like to offer a frame challenge. As noted in the comments, particularly by Ian Bush, pointers in Fortran are notoriously error-prone.
I would recommend replacing any allocated pointer
s with allocatable
s. These allocatable
s also need to be target
s if they have pointer
s pointing at them, like so:
module mo_zoo
implicit none
type zoo
integer, dimension(:,:), allocatable :: animals
integer, dimension(:), pointer :: tigers
integer, dimension(:), pointer :: ducks
end type zoo
save
type(zoo), dimension(:), allocatable, target :: zoos
end module mo_zoo
program test
use mo_zoo
implicit none
integer :: n_zoos
integer :: i
n_zoos = 4
allocate(zoos(n_zoos))
do i = 1, n_zoos
allocate(zoos(i)%animals(10, 2))
zoos(i)%tigers => zoos(i)%animals(:, 1)
zoos(i)%ducks => zoos(i)%animals(:, 2)
end do
end program test
There are a number of advantages to using allocatable
s over pointer
s where possible:
allocatable
s will automatically be freed when the allocatable
s drop out of scope1.allocatable
s than about pointer
s, sometimes leading to faster code.1 At least, this is true according to the Fortran standard. There are several outstanding problems with some compilers (notably this bug) relating to finalisation.
Upvotes: 5