i'm running in some trouble when trying to pass some derived types to subroutines for their allocation:
here some small example i created to explaining my problem:
the module containing the derived type:
module type implicit none private public :: mt, rk, ik, ck integer, parameter :: digits = 8 integer, parameter :: decades = 9 integer, parameter :: rk = selected_real_kind(digits) integer, parameter :: ik = selected_int_kind(decades) integer, parameter :: ck = selected_char_kind('default') type set character(kind=ck,len=80) :: name integer(ik), allocatable :: members(:) end type set type mytype type(set), allocatable :: nset(:) end type mytype type(mytype) :: mt end module type
and the module containing the subroutines:
module allocating_sub use type, only : ik, rk, ck implicit none private public :: allocating interface allocating module procedure allocating_real_1d, allocating_int_1d, allocating_char_1d end interface contains subroutine allocating_real_1d(vec,length) implicit none real(rk), allocatable, intent(inout) :: vec(:) integer(ik), intent(in) :: length if(allocated(vec)) deallocate(vec) allocate(vec(length)) end subroutine allocating_real_1d subroutine allocating_int_1d(vec,length) implicit none integer(ik), allocatable, intent(inout) :: vec(:) integer(ik), intent(in) :: length if(allocated(vec)) deallocate(vec) allocate(vec(length)) end subroutine allocating_int_1d subroutine allocating_char_1d(vec,length) implicit none character(*), allocatable, intent(inout) :: vec(:) integer(ik), intent(in) :: length if(allocated(vec)) deallocate(vec) allocate(vec(length)) end subroutine allocating_char_1d end module allocating_sub
and finaly the main part:
program test use type, only : ik, rk, ck, mt use allocating_sub implicit none integer(ik), parameter :: nnsets = 4 call allocating (mt%nsets(:),nnsets) end program test
when i try to run this i get the following error:
error #6285: There is no matching specific subroutine for this generic subroutine call. [ALLOCATING]
Now i am asking myself how to write a subroutine allocating_xx which is able to handle such structures.
the following solution works but strongly impairs the readabilty of the main code if large type-structures are used:
if (allocated(mt%nset)) deallocate(mt%nset) ; allocate(mt%nset(nnsets))
The problem is this:
call allocating (mt%nsets(:),nnsets)
Get rid of the (:) - it completely changes the meaning of what you're doing here. See here for more.
thank you for your fast reply.
I already tried this, but the error still remains.
This would work totally fine if mt%nset was the final / lowest "level" of the type mt.
I only get this error if "sublevels" like mt%nset%name exist and i try to allocate mt%nset(1:nnsets) via subroutine call.
small correction to the above code: mt%nsets has to be mt%nset
Ok. You did need to remove the (:) as the (:) makes the argument incompatible with the ALLOCATABLE attribute.
The more basic problem is that you are passing something of type SET where the generic has corresponding dummy arguments of type real, integer or character. It's not clear to me what you want to do here - how do you want to decide what type to allocate?
There seems to be something missing here. Can you explain in more detail what you want to accomplish? If you want a component that can be of multiple types, you could make it CLASS(*) but then would have to explicitly specify the type when allocating.
Ok, i will try to make it more clear
Let's say i have a base type set. A set has a name set%name and consists of an unknown amount of members set%members
type set character(*) :: name integer(ik), allocatable :: members(:) end type set
Further i have a database this database consits of a unknown (at least at that point) amount of sets
type database type(set), allocatable :: set(:) integer(ik) :: nsets end type database
Then an external input-file is read. There the amount of sets (database%nsets) in the database can be evaluated. And now i want to asign this dimension to the database%set(1:database%nsets). This works totally fine using:
if (allocated(database%set)) deallocate(database%set) ; allocate(database%set(database%nsets))
But since the code has a lot of lines (plus i have to use this multiple times) and the name of the types and their derived types are pretty long i wanted to put this into a suibroutine to improve readability since i am the only one woring on this code, but not the only one using it.
What you describe here is easy, but I don't see how it relates to having integer, real and character allocating routines. You can have a single allocate routine that gets passed database%set and allocates it to the desired size.
Jan M. wrote:
.. it seems like I complicated things way too much...
With (re)allocate on assignment facility in the Fortran standard that is very convenient with intrinsic types as well as derived types whose components do not have attributes that might complicate matters (e.g., POINTERs) or subcomponents thereof, do you even need the overloaded "allocating" procedure?
thank you very much, i was not aware of this compiler-option (i found out it was turned off).
You are right, considering this i don't need the overloaded subroutine.