I want to overload the assignment for a type that I want to use for polymorphic pointers. I dont know the actual subtype the pointer is holding on runtime. But the following example code reproduces the strange compiler error I get:
module example
type :: base_class
real(4) :: some_garbage
contains
end type
type, extends(base_class) :: sub_class
real(4) :: even_more_garbage
contains
end type
type :: main_operations_t
class(base_class), pointer :: basic_pointer
class(base_class), pointer :: pointer_array(:)
contains
procedure :: main_operations
end type
interface assignment(=)
module procedure assign_base_class
end interface
contains
subroutine assign_base_class(result_object, input_object)
implicit none
class(base_class), pointer, intent(out) :: result_object
class(base_class), pointer, intent(in) :: input_object
result_object%some_garbage = input_object%some_garbage
end subroutine
subroutine main_operations(this)
implicit none
class(main_operations_t) :: this
class(base_class), pointer :: hack
allocate(this%basic_pointer)
allocate(this%pointer_array(2))
this%basic_pointer%some_garbage = 0.0
this%pointer_array(1)%some_garbage = 1.0
this%pointer_array(2)%some_garbage = 2.0
this%basic_pointer = this%pointer_array(1)
this%pointer_array(1) = this%pointer_array(2)
this%pointer_array(2) = this%basic_pointer
this%basic_pointer = this%pointer_array(1)
hack => this%pointer_array(1)
hack = this%pointer_array(2)
hack => this%pointer_array(2)
hack = this%basic_pointer
end subroutine
end module
When I try to assign to the indexed pointer array i.e
this%pointer_array(1) = this%pointer_array(2)
this%pointer_array(2) = this%basic_pointer
I use gfortran 4.8.4 on Ubuntu. I get a compiler error:
Error: Variable must not be polymorphic in intrinsic assignment at (1) - check that there is a matching specific subroutine for '=' operator
The assignment to the 0d pointer however works without complaints. The section with the "hack" pointer shows a possible workaround to get this to work in an ugly manner.
The compiler is complaining it needs a defined assignment. You do have one, but it requires pointers:
subroutine assign_base_class(result_object, input_object)
class(base_class), pointer, intent(out) :: result_object
class(base_class), pointer, intent(in) :: input_object
(It is not necessary to repeat implicit none
in all module procedures. I'd argue it is a clutter which harms readability.)
And your variables are not pointers. pointer_array(1)
is NOT a pointer even though pointer_array
is a pointer.
A solution is to remove the unneeded pointer attribute:
subroutine assign_base_class(result_object, input_object)
class(base_class), intent(out) :: result_object
class(base_class), intent(in) :: input_object
result_object%some_garbage = input_object%some_garbage
end subroutine
This compiles cleanly.
It would make sense to have the pointer
attribute there if you were doing pointer assignment, but as it stands, there is no use of it in the defined assignment.