Reputation: 730
I have type-bound procedures which I want to accept an array as their passed dummy argument (getMean
and assignEachThatInThis
below). This does not compile though. I have read Metcalf et al. and they do not say that the passed dummy argument must be scalar and I don't really understand why that would have to be the case anyway.
If I use the nopass
attribute it does compile and so it does when the procedures are not type-bound ones.
Can someone, please, explain what is going on and what is and is not safe to do?
Here is my example:
module types
implicit none
integer, parameter :: DP = selected_real_kind(r=250,p=13)
type :: my_type1
real(KIND=DP), dimension(:), allocatable :: elem1 ! interest rate
contains
procedure :: getMean => getMean_my_type1
procedure :: assignThatInThis_my_type1
procedure :: assignEachThatInThis_my_type1
generic :: assignment (=) => assignThatInThis_my_type1, assignEachThatInThis_my_type1
end type my_type1
contains
subroutine assignThatInThis_my_type1(this,that)
! Defines the overloaded `=` operator for the 'my_type1' class
! this = that
class(my_type1), intent(inout) :: this
class(my_type1), intent(in) :: that
this%elem1 = that%elem1
end subroutine assignThatInThis_my_type1
subroutine assignEachThatInThis_my_type1(this,that)
!--> this is apparently illegal, 'this' has to be a scalar :-(
!--> in principle it could work with the 'nopass' attribute (see 'getMean_my_type1') but that won't work with the assignment operator '='
class(my_type1), dimension(:), intent(inout) :: this
class(my_type1), dimension(:), intent(in) :: that
integer :: i
do i = 1,size(this,1)
this(i) = that(i)
end do
end subroutine assignEachThatInThis_my_type1
subroutine getMean_my_type1(this,that)
class(my_type1), dimension(:), intent(inout) :: this
class(my_type1), intent(inout) :: that
integer :: nTypes
integer :: n
integer :: j
nTypes = size(this,1)
n = size(this(1)%elem1,1) ! length of the simulation
! sum all elem1
do j = 1,nTypes
that%elem1 = that%elem1 + this(j)%elem1
end do
! divide by the number of elements
that%elem1 = that%elem1 / real(nTypes)
end subroutine getMean_my_type1
end module types
program pdatest
implicit none
end program pdatest
The following works, where I use the nopass
attribute for getMean
and don't have the assignment subroutines type-bound:
type :: my_type1
real(KIND=DP), dimension(:), allocatable :: elem1 ! interest rate
contains
procedure, nopass :: getMean => getMean_my_type1
end type my_type1
interface assignment (=)
module procedure assignEachThatInThis_my_type1, assignThatInThis_my_type1
end interface
Upvotes: 1
Views: 402
Reputation: 32451
To start, the passed-object dummy is required to be scalar (among other things) directly because of the rules of Fortran. Consider F2008, C456:
The passed-object dummy argument shall be a scalar, nonpointer, nonallocatable dummy data object with the same declared type as the type being defined; ...
With the nopass
attribute the type-bound procedure reference has no passed-object, so this restriction does not apply. Equally, if you make the subroutine reference not from its type binding, the restriction doesn't apply.
With the getMean
binding, the desire is to reduce an array to a scalar, but with the assignment the wish is to have an input array and an output array of the same shape. This latter is a case for an elemental subroutine.
Upvotes: 1