My IDE is: Code::Blocks 20.03 ( MinGW 9.2.0 )
This is my simple code:
module mod_kompleks
use, intrinsic :: iso_c_binding, only : rp => c_double
implicit none
type, public :: kom_bro
private
real(rp) :: dio_rea
real(rp) :: dio_img
contains
procedure, private :: kom_bro_sab ! 16 line
generic, public :: operator(+) => kom_bro_sab ! 18 line
end type kom_bro
interface kom_bro
module procedure :: kom_bro_set
end interface kom_bro
contains
! procedure - kom_bro_set
type(kom_bro) function kom_bro_set(rea_part, img_part) result(bro_c)
real, intent(in) :: rea_part, img_part
bro_c%dio_rea = rea_part
bro_c%dio_img = img_part
end function kom_bro_set
! procedure - kom_bro_sab
function kom_bro_sab(bro_a, bro_b) result(bro_c)
type(kom_bro), intent(in) :: bro_a
type(kom_bro), intent(in) :: bro_b
type(kom_bro) :: bro_c
bro_c%dio_rea = bro_a%dio_rea + bro_b%dio_rea
bro_c%dio_img = bro_a%dio_img + bro_b%dio_img
end function kom_bro_sab
end module mod_kompleks
program kompleksni_broj
use, non_intrinsic :: mod_kompleks
implicit none
integer :: i
type(kom_bro) :: broj_01(3)
type(kom_bro) :: broj_02(3)
type(kom_bro) :: broj_03(3)
do i = 1, 3
broj_01(i) = kom_bro(i + 2.2,i + 3.3)
broj_02(i) = kom_bro(i + 4.4,i + 5.5)
broj_03(i) = broj_01(i) + broj_02(i)
end do
end program kompleksni_broj
I intend to define a user type that would look like a complex number but would also allow the arithmetic operation of adding two complex numbers. Since I am not experienced in the programming language Fortran in my example I came across a problem where the compiler reports the following errors to me:
|16|Error: Non-polymorphic passed-object dummy argument of 'kom_bro_sab'
|18|Error: Undefined specific binding 'kom_bro_sab' as target of GENERIC '+'
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
My knowledge of OOP in the programming language Fortran is not enough for me to be able to solve this problem on my own. Is it even possible to define such a user-defined type?
You have multiple errors. Most important the operator overloading is wrong. See my example implementation below.
Derived data type for complex numbers (file name b.f90
)
module mod_kompleks
use, intrinsic :: iso_c_binding, only : rp => c_double
implicit none
private
public kom_bro
public operator(+)
type kom_bro
private
real(rp) :: dio_rea
real(rp) :: dio_img
contains
procedure :: init => kom_bro_init
procedure :: print => kom_bro_print
end type
interface operator(+)
module procedure kom_bro_sab
end interface
interface kom_bro
module procedure kom_bro_init2
end interface
contains
function kom_bro_init2(rea_part, img_part) result(bro)
real(rp), intent(in) :: rea_part
real(rp), intent(in) :: img_part
type(kom_bro) :: bro
call bro%init(rea_part, img_part)
end function
subroutine kom_bro_init(this, rea_part, img_part)
class(kom_bro), intent(out) :: this
real(rp), intent(in) :: rea_part
real(rp), intent(in) :: img_part
this%dio_rea = rea_part
this%dio_img = img_part
end subroutine
subroutine kom_bro_print(this)
class(kom_bro), intent(in) :: this
print *, this%dio_rea, this%dio_img
end subroutine
function kom_bro_sab(bro_a, bro_b) result(bro_c)
type(kom_bro), intent(in) :: bro_a
type(kom_bro), intent(in) :: bro_b
type(kom_bro) :: bro_c
bro_c%dio_rea = bro_a%dio_rea + bro_b%dio_rea
bro_c%dio_img = bro_a%dio_img + bro_b%dio_img
end function
end module
Program (file name a.f90
)
program kompleksni_broj
use mod_kompleks
use, intrinsic :: iso_c_binding, only : rp => c_double
implicit none
integer :: i
type(kom_bro) :: broj_01(3), broj_02(3), broj_03(3)
do i = 1, 3
call broj_01(i)%init(i + 2.2_rp, i + 3.3_rp) ! initialization via type-bound routine
broj_02(i) = kom_bro(i + 4.4_rp, i + 5.5_rp) ! initialization via interface kom_bro aka "type constructor"
broj_03(i) = broj_01(i) + broj_02(i)
call broj_03(i)%print()
end do
end program
Output
$ gfortran -g3 -Wall -fcheck=all b.f90 a.f90 && ./a.out
3.2000000000000002 5.4000000000000004 8.6000000000000014
4.2000000000000002 6.4000000000000004 10.600000000000001
5.2000000000000002 7.4000000000000004 12.600000000000001