Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Getter functions for arrays

zp3
Beginner
414 Views

Hi,

I wonder if there exists an easy way to implement a getter function for an array valued attribute?

For instance, one has a derived item, for example the extensions of a process grid (pgrid). As this item can be retrieved lets say from an mpi subroutine using a given communcator, it would be cleaner not to store this informations redundantly:

...

type :: PGRID
    integer :: comm
  contains
    procedure :: psizes => get_psizes
end type PGRID

...

module function get_psizes(this) result(psizes)
    class(PGRID), intent(in) :: this
    integer :: psizes(2)
end function get_psizes

...

! now if one wants to access 'psizes' like an array, 
! that does obviously produce an error because indexing
! is interpreted as  a second argument

dim1=pgrid%psizes(1)  ! -> error

 

I have found this more complicated workaraound, so that indexing should work, but I'm not very happy with it:

type :: PGRID
    integer :: comm
  contains
    procedure psizes => get_psizes
end type PGRID

...

interface get_psizes
    module function get_psizes_array(this,k) result(psizes)
        class(PGRID), intent(in) :: this
        integer, optional, intent(in) :: k(:)
        integer :: psizes(size(k))
    end function get_psizes_array

    module function get_psizes_single(this,k) result(psizes)
        class(PGRID), intent(in) :: this
        integer, optional, intent(in) :: k
        integer :: psizes
    end function get_psizes_single
end interface get_psizes

So is there any better solution for this problem?

- Thanks in advance

0 Kudos
1 Solution
FortranFan
Honored Contributor III
414 Views

Are you looking for something like this?  Look at the couple of different options, a function accepting an index and returning a scalar and another that returns a vector that can be used in multiple ways but shown below with an ASSOCIATE construct.

module m

   implicit none

   type :: t
      integer :: i(2)
   contains
      private
      procedure, pass(this) :: get_i_scalar
      procedure, pass(this) :: get_i_vector
      generic, public :: get_i => get_i_scalar, get_i_vector
   end type

contains

   pure function get_i_scalar(this, idx) result(ival)

      class(t), intent(in) :: this
      integer, intent(in)  :: idx
      !.. function result
      integer :: ival

      !.. checks elided
      ival = this%i(idx)

      return

   end function get_i_scalar

   pure function get_i_vector(this) result(ival)

      class(t), intent(in) :: this
      !.. function result
      integer :: ival(size(this%i))

      !.. checks elided
      ival = this%i

      return

   end function get_i_vector

end module m
program p

   use m, only : t

   implicit none

   type(t) :: foo
   integer :: i1
   integer :: i2

   foo%i = [ 1, 2 ]

   i1 = foo%get_i(1)
   print *, " i1 = ", i1

   asc: associate ( i => foo%get_i() )
      i2 = i(2)
      print *, " i2 = ", i2
   end associate asc

   stop

end program p

 

View solution in original post

0 Kudos
1 Reply
FortranFan
Honored Contributor III
415 Views

Are you looking for something like this?  Look at the couple of different options, a function accepting an index and returning a scalar and another that returns a vector that can be used in multiple ways but shown below with an ASSOCIATE construct.

module m

   implicit none

   type :: t
      integer :: i(2)
   contains
      private
      procedure, pass(this) :: get_i_scalar
      procedure, pass(this) :: get_i_vector
      generic, public :: get_i => get_i_scalar, get_i_vector
   end type

contains

   pure function get_i_scalar(this, idx) result(ival)

      class(t), intent(in) :: this
      integer, intent(in)  :: idx
      !.. function result
      integer :: ival

      !.. checks elided
      ival = this%i(idx)

      return

   end function get_i_scalar

   pure function get_i_vector(this) result(ival)

      class(t), intent(in) :: this
      !.. function result
      integer :: ival(size(this%i))

      !.. checks elided
      ival = this%i

      return

   end function get_i_vector

end module m
program p

   use m, only : t

   implicit none

   type(t) :: foo
   integer :: i1
   integer :: i2

   foo%i = [ 1, 2 ]

   i1 = foo%get_i(1)
   print *, " i1 = ", i1

   asc: associate ( i => foo%get_i() )
      i2 = i(2)
      print *, " i2 = ", i2
   end associate asc

   stop

end program p

 

0 Kudos
Reply