Unlimited Polymorphic Data Structures in Fortran

March 20, 2010

This article was originally posted to comp.lang.fortran on March 19, 2010.

I’ve been experimenting with using unlimited polymorphic pointers (e.g., class(*), pointer :: p) to build generic data structures and I wondered if anyone might have suggestions about how to improve the interface. I have in mind lists, hash tables, etc., but the important components are simply a container with a pointer and procedures to get and set the pointer, so I’ll use that as a starting point:

module container
  implicit none

  type :: container_t
     private
     class(*), pointer :: p
  end type container_t

contains

  subroutine container_set(self, p)
    type(container_t), intent(inout) :: self
    class(*), target, intent(in) :: p
    self%p => p
  end subroutine container_set

  subroutine container_get(self, p)
    type(container_t), intent(inout) :: self
    class(*), pointer, intent(out) :: p
    p => self%p
  end subroutine container_get

end module container

The set subroutine has a non-pointer polymorphic argument (with the target attribute), so we can pass it things directly without first setting a pointer. The difference being that we can write:

type(container_t) :: c
type(mytype_t), target :: foo

call container_set(c, foo)

as opposed to:

type(container_t) :: c
type(mytype_t), target :: foo
class(*), pointer :: p

p => foo
call container_set(c, p)

So we can avoid some work in the set procedure, and this all seems pretty natural, but in order to retrieve the pointer and do something with the data, this is the simplest thing I can come up with:

type(container_t) :: c
class(*), pointer :: p

call container_get(c, p)

select type (p)
type is (mytype_t)
  ! do something with p now
end select

In this case, since we know the type of p, the select type block seems like overkill, but I don’t think it can be avoided. If it had to be done often though, one could place all of this in a helper function in practice, when the type is known. However, I’d be happy to hear if anyone knows of a more natural or less verbose way to get the data out of the container, or any suggestions for improving the interface overall.