Georgy
Georgy

Reputation: 13687

Calling type-bound procedure for an array of derrived types in Fortran

Let's assume that I have a derived type Coordinates with its type-bound procedure swap:

module myTypes
    implicit none
    public :: Coordinates  

    type Coordinates
        real :: x,y
    contains
        procedure :: swap  ! Error here
    end type
contains
    subroutine swap(this)
        class (Coordinates) :: this
        this%x = this%x + this%y
        this%y = -(this%y - this%x)
        this%x = this%x - this%y
    end subroutine
end module

Now, if I have an instance of Coordinates called point_A, and if I want to call the type-bound procedure swap for it, I would just write: call point_A%swap. But if I have an array of instances of Coordinates, like:

type(Coordinates), dimension(:), allocatable :: setOfPoints

then to call the swap for all the elements of setOfPoints, I would like to write:

call setOfPoints(:)%swap

In order to achieve that, I change the code of swap procedure to:

subroutine swap(these)
        class (Coordinates), dimension(:)  :: these
        integer :: i
        do i = 1, size(this)
            this(i)%x = this(i)%x + this(i)%y
            this(i)%y = -(this(i)%y - this(i)%x)
            this(i)%x = this(i)%x - this(i)%y
        end do
end subroutine

Unfortunately, gfortran doesn't like my idea. On the line that I marked in the first piece of code it says:

Error: Passed-object dummy argument of 'swap' must be scalar.

Question: how can I call the type-bound procedure for all the instances of the derived type at once? I don't want to put the call in the loop, but I want to do this as I wrote it before, like what we always do with arrays in Fortran.

I read about the ELEMENTAL keyword, but if I want to use it, I need the type-bound procedure to be 'pure', which is not my case. I tried to place a DEFERRED keyword after the word procedure, but then compiler says:

Error: Interface must be specified for DEFERRED binding

I created an interface for swap, but I couldn't figure out where to place it. I tried many positions and compiler said that 'interface was unexpected there'. Also, I read about SELECT TYPE, but I think it won't help in my case.

Upvotes: 3

Views: 465

Answers (1)

Your specific example is perfectly fine with ELEMENTAL

module myTypes
    implicit none
    public :: Coordinates  

    type Coordinates
        real :: x,y
    contains
        procedure :: swap  ! Error here
    end type
contains
    elemental subroutine swap(this)
        class (Coordinates), intent(inout) :: this
        this%x = this%x + this%y
        this%y = -(this%y - this%x)
        this%x = this%x - this%y
    end subroutine

end module

 use myTypes

 type(Coordinates) :: arr(10)

 arr = Coordinates(1.,2.)

 call arr%swap

 end

Your subroutine is pure. If it cannot be, consider using impure elemental.

Upvotes: 2

Related Questions