On 2013-05-17 10:01 PM, \"Vladimír Fuka <\"name.surname at >> wrote:
>
> Hi,
> it is easy to reallocate an add an item to a non-polymorphic array
>
> subroutine add_element_int(a,e)
> integer,allocatable,intent(inout) :: a(:)
> integer,intent(in) :: e
> integer,allocatable :: tmp(:)
>
> if (.not.allocated(a)) then
> a = [e]
> else
If you are lazy like me, then:
a = [ a, e ]
is less typing and clearer from a programmer intent point of view (but
likely to have much more execution overhead with current compilers).
Note you are not just talking a polymorphic array - you've got an
unlimited polymorphic array. Consequently:
Perhaps I'm off base here, but I think your intent is to have a generic
procedure (in the sense of "applicable to any type") that appends to an
array, where the thing being appended has the same dynamic type as the
array being appended to. This requirement is potentially compile time
checkable in the non-polymorphic case, but is runtime implied with your
memcpy approach. At the time the call sites of you procedure are
compiled, really all you want to do is "replace" INTEGER with whatever
the relevant dynamic type is for the arguments at that call site.
Basically - you are trying to do generic programming.
Fortran's processor based support for generic programming is poor -
though as often posted on c.l.f. there are source code "hacks" using
INCLUDE etc that help you around this. While these hacks are messy from
a source code appearance point of view, they will probably give you a
much better outcome from the point of view of the code that the compiler
executes, and potentially things like compiler error checking, etc.
(And then you can join the chorus of people begging for better
in-language support of generic programming.)
This is probably further off-base, but a similar situation could be
where you want to have an array of things that could be of any dynamic
type, and you want to append a new object (again of any dynamic type) to
it. In that case, the array is of container type:
TYPE :: Container
CLASS(*), ALLOCATABLE :: item
END TYPE Container
and then append operation is then on a *non-polymorphic* array dummy of
that type:
SUBROUTINE add_element_(a, e)
TYPE(Container), INTENT(INOUT), ALLOCATABLE :: a(:)
CLASS(*), INTENT(IN) :: e
IF (.NOT. ALLOCATED(a)) THEN
a = [ Container(e) ]
ELSE
a = [ a, Container(e) ] ! Being lazy again.
END IF
END SUBROUTINE add_element_
(The definition of a unlimited polymorphic component via a structure
constructor might be erroneous in F2003 (not sure, ridiculous
restriction if so), but there are a couple of ways of working around
this if that is the case and I think the use is ok in F2008.)
If all elements are of the same dynamic type, then you have equivalent
storage (but not exactly the same "use") as your polymorphic array
growing thing. Client code would need to be doing lots of SELECT TYPE
on the array elements in order to do anything useful with the stored
objects, but presumably client code knows what it has been stuffing
inside the array.
(If you are using ifort then this thread
http://software.intel.com/en-us/forums/topic/326077
identifies some potential compiler issues with this approach (see in
particular the .f90 that appear as attachments later on), that may have
been fixed by now. In the source examples in that thread the items are
just polymorphic, not unlimited polymorphic, but many aspects are common.)