I am writing object destructors in Fortran, using the final
keyword in the type definition. But the destructor is not called when an array of those instances leave the scope.
module problem_module
type :: destructable_object
integer :: nr
contains
final :: destruct
end type destructable_object
type :: collection
type(destructable_object) :: single_member
type(destructable_object), dimension(3) :: multiple_members
end type collection
contains
subroutine destruct(instance)
type(destructable_object), intent(in) :: instance
write(*,*) "Destruct ",instance%nr
end subroutine destruct
end module problem_module
In this example module, any scalar of the destructable_object
type will be deconstructed with the destruct routine induced by the final
keyword. Arrays of the destructable_object
type will, however, not be deconstructed. For destructable
objects in other classes will also only be properly deconstructed if they are scalar (In this example, the single_member gets deconstructed properly, the multiple_members not). This is independent of whether or not the containing object is in an array or not. So, for example
program main
! Destructors are only called at end of subroutines, not at the end of the program.
! Therefore, I move the entire program to a subroutine.
call main_execute
contains
subroutine main_execute
use problem_module
implicit none
type(destructable_object) :: single_instance
type(destructable_object), dimension(3) :: multiple_instances
type(collection) :: single_collection
type(collection), dimension(3) :: multiple_collections
single_instance%nr = 1
multiple_instances(1)%nr = 2
multiple_instances(2)%nr = 3
multiple_instances(3)%nr = 4
single_collection%single_member%nr = 5
single_collection%multiple_members(1)%nr = 6
single_collection%multiple_members(2)%nr = 7
single_collection%multiple_members(3)%nr = 8
multiple_collections(1)%single_member%nr = 9
multiple_collections(1)%multiple_members(1)%nr = 10
multiple_collections(1)%multiple_members(2)%nr = 11
multiple_collections(1)%multiple_members(3)%nr = 12
multiple_collections(2)%single_member%nr = 13
multiple_collections(2)%multiple_members(1)%nr = 14
multiple_collections(2)%multiple_members(2)%nr = 15
multiple_collections(2)%multiple_members(3)%nr = 16
multiple_collections(3)%single_member%nr = 17
multiple_collections(3)%multiple_members(1)%nr = 18
multiple_collections(3)%multiple_members(2)%nr = 19
multiple_collections(3)%multiple_members(3)%nr = 20
end subroutine main_execute
end program main
returns
Destruct 1
Destruct 5
Destruct 9
Destruct 13
Destruct 17
Exactly all the scalar instances of the destructable
object and not the arrays of the destructable
objects, independent of their situation. If I want an array of objects with a destructor, I can fix that by adding a layer of indirectness with a container object. That seems clumsy, requiring nested %-constructions or a bunch of pointers. Is there a more elegant way to force the destruction of arrays?