First of all, Hi to everyone ! Wish you all a good starting week :)
In enhancing (as well as simplifying some syntax) a previously developed Derived Type, I was (and some still) encountering some errors as in the title specification (NOTE: for details about full messages and their cause, please read the comment lines in the code below :) ).
Among them, the ones I was not understand the most (of the why I am getting them) are error #6355: This binary operation is invalid for this data type. for the operator(==), and error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. for the assignment(=).
Here is an example of source code (NOTE: in order to reproduce those errors, comment out the type-bound procedure part, and uncomment out the two interface bodies):
module MPolicyMod
implicit none
private
public :: MPolicy
type, public :: MPolicy_t
real(kind = 8) :: delta_fI_fct_
real(kind = 8) :: delta_fJ_fct_
real(kind = 8) :: interp_I_fct_
real(kind = 8) :: interp_J_fct_
integer :: id_pol_
contains
generic :: assignment(=) => MPolicy_fromPol_sub, MPolicy_fromID_sub
procedure, private, pass :: MPolicy_fromID_sub, MPolicy_fromPol_sub
generic :: operator(==) => MPolicy_isID
procedure, pass, private :: MPolicy_isID
end type MPolicy_t
integer, public, parameter :: MPolicy_NULL = 0
integer, public, parameter :: MPolicy_DEF = 1
integer, public, parameter :: MPolicy_CONST = 2
interface MPolicy_t
module procedure MPolicy_constructor_integer
module procedure MPolicy_constructor_real
module procedure MPolicy_fromID
end interface
! interface assignment(=)
! module procedure MPolicy_fromPol_sub
! module procedure MPolicy_fromID_sub
! end interface assignment(=)
! interface operator(==)
! module procedure MPolicy_isID
! end interface operator(==)
contains
!> Main default constructor.
function MPolicy_constructor_real(dfi, dfj, interpi, interpj, id) result(pol)
real(kind = 8), intent(in) :: dfi, dfj, interpi, interpj
integer, intent(in) :: id
type(MPolicy_t) :: pol
print *, ' Default constructor (as compiler)...'
pol%delta_fI_fct_ = dfi
pol%delta_fJ_fct_ = dfj
pol%interp_I_fct_ = interpi
pol%interp_J_fct_ = interpj
pol%id_pol_ = id
end function MPolicy_constructor_real
function MPolicy_constructor_integer(dfi, dfj, interpi, interpj, id) result(pol)
integer, intent(in) :: dfi, dfj, interpi, interpj, id
type(MPolicy_t) :: pol
print *, ' Default constructor (integer version)...'
pol = MPolicy_t(real(dfi, 8), &
real(dfj, 8), &
real(interpi, 8), &
real(interpj, 8), id)
end function
function MPolicy_fromID(id) result(pol)
integer, intent(in) :: id
type(MPolicy_t) :: pol
print *, ' Constructor from ID...'
select case (id)
case (MPolicy_NULL)
return
case (MPolicy_DEF)
pol = MPolicy_t(2, 2, 2, 2, MPolicy_DEF)
case (MPolicy_CONST)
pol = MPolicy_t(1, 1, 1, 1, MPolicy_CONST)
case default
block
character(len=3) :: fmt
write(fmt, '(i)'), id
stop ' [ERROR] Unknow policy identifier "id"= '//fmt
end block
end select
end function MPolicy_fromID
subroutine MPolicy_fromPol_sub(lhs, rhs)
class(MPolicy_t), intent(in) :: rhs
class(MPolicy_t), intent(out) :: lhs
lhs%delta_fI_fct_ = rhs%delta_fI_fct_
lhs%delta_fJ_fct_ = rhs%delta_fJ_fct_
lhs%interp_I_fct_ = rhs%interp_I_fct_
lhs%interp_J_fct_ = rhs%interp_J_fct_
lhs%id_pol_ = rhs%id_pol_
end subroutine MPolicy_fromPol_sub
subroutine MPolicy_fromID_sub(lhs, rhs)
class(MPolicy_t), intent(out) :: lhs
integer, intent(in) :: rhs
lhs = MPolicy_t(rhs)
end subroutine MPolicy_fromID_sub
function MPolicy(mpol) result(pol)
integer :: mpol
type(MPolicy_t) :: pol
pol = MPolicy_t(mpol)
end function MPolicy
pure function MPolicy_isID(pol, id) result(isID)
class(MPolicy_t), intent(in) :: pol
integer, intent(in) :: id
logical :: isID
isID = pol%id_pol_ == id
end function MPolicy_isID
end module
Example program:
program test
use MPolicyMod
implicit none
! ! NOTE: generates
! ! error #6259: This array or function or substring is invalid in constant expressions. [MPOLICYMOD^MPOLICY_FROMID]
! ! error #7715: Replacing invalid structure constructor by integer 1. [<NULL_STRING>]
! type(MPolicy_t) :: pol = MPolicy_t(MPolicy_NULL)
type(MPolicy_t) :: pol
! =========================================================================
print *, pol
pol = MPolicy_t(MPolicy_NULL)
print *, pol
! ! NOTE: generates (without TYPE-BOUND specification)
! ! error #6355: This binary operation is invalid for this data type.
print *, pol == MPolicy_NULL
pol = MPolicy_t(1, 1, 1, 1, 2)
print *, pol
! ! NOTE: generates (without TYPE-BOUND specification)
! ! error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands.
pol = MPolicy_DEF
print *, pol
end program test
Then, after reading through the ISO Fortran Standard 2003 Draft document, at Section 4.5.4 Type-bound procedures, Rule R452 states that we could specify assignment(=) as a generic-spec, in a generic-binding type of proc-binding-stmt. There I realised I was missing the type-bound specifications for those operator/assignment procedures.
Why, then, only the interface body was not enough to make it work?
After this, I also wonder why the initialisation statement type(MPolicy_t) :: pol = MPolicy_t(MPolicy_NULL) generates errors #6259 and #7715.
For that, I still didn't search by my own. But if you come with an asnwer before I might find (hopefully) an explanation, it's always good to have constructive as well as polite discussions with You all.
I now go back to my searching. Have a nice day :)