Hope you find some useful tool for this. Or, those pursuing more tooling for Fortran will create something along such lines!
In the meantime, users willing to put in the work themselves in the absence of tooling can consider mimicking what’s available in other stronger OO-based approaches as part of the languages such as a built-in “superclass” with some hashcode facility and have their derived types extend from it. Users may find this alleviate their “boilerplate” code somehat.
module base_m
type, abstract :: base_t
private
integer :: m_hash = 0
contains
private
procedure, pass(lhs) :: IsEqual_t
procedure, pass(lhs) :: IsNotEqual_t
procedure, pass(this), public :: SetHash
generic, public :: operator(==) => IsEqual_t
generic, public :: operator(/=) => IsNotEqual_t
end type
contains
subroutine SetHash( this, hash )
! Argument list
class(base_t), intent(inout) :: this
integer, intent(in) :: hash
this%m_hash = hash
return
end subroutine
function IsEqual_t( lhs, rhs ) result( IsEqual )
! Argument list
class(base_t), intent(in) :: lhs
class(base_t), intent(in) :: rhs
! Function result
logical :: IsEqual
IsEqual = lhs%m_hash == rhs%m_hash
return
end function
function IsNotEqual_t( lhs, rhs ) result( IsNotEqual )
! Argument list
class(base_t), intent(in) :: lhs
class(base_t), intent(in) :: rhs
! Function result
logical :: IsNotEqual
IsNotEqual = lhs%m_hash /= rhs%m_hash
return
end function
end module
module date_m
use base_m, only : base_t
type, extends(base_t) :: date_t
integer :: year = 0
integer :: month = 0
contains
private
procedure, pass(this) :: SetDateToday
procedure, pass(this) :: SetDateArbitrary
generic, public :: SetDate => SetDateToday, SetDateArbitrary
end type
contains
subroutine SetDateToday( this )
! Argument list
class(date_t), intent(inout) :: this
! Local variables
integer :: vals(8)
call date_and_time( values=vals )
this%year = vals(1)
this%month = vals(2)
call this%SetHash( hash=(vals(2)*12 + vals(1)) )
end subroutine
subroutine SetDateArbitrary( this, year, month )
! Argument list
class(date_t), intent(inout) :: this
integer, intent(in) :: year
integer, intent(in) :: month
! Checks elided
this%year = year
this%month = month
call this%SetHash( hash=(year*12 + month) )
end subroutine
end module
use date_m, only : date_t
type(date_t) :: Today
type(date_t) :: Bday
call Today%SetDate()
call Bday%SetDate( 1990, 1 )
if ( Today /= Bday ) then
print *, "Today is not it :-("
else
print *, "Happy returns for the day!"
end if
end
C:\Temp>gfortran -std=f2018 -Wall p.f90 -o p.exe
C:\Temp>p.exe
Today is not it 
C:\Temp>