From: Paul Richard Thomas <paul.richard.thomas@gmail.com>
To: "fortran@gcc.gnu.org" <fortran@gcc.gnu.org>
Cc: Steve Lionel <steve@stevelionel.com>
Subject: Overriding intrinsic operators
Date: Fri, 1 Jan 2021 16:14:46 +0000 [thread overview]
Message-ID: <CAGkQGi+WB-vrx_G=k=V49WGo+orB6a52hAPowB2M1q7TOXpb6Q@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1829 bytes --]
Hi All,
Happy New Year!
I took an interest in a recent clf thread, entitled "comparison between
class(*) instances", and submitted an example of a possible implementation.
I have attached a reduced version of it.
gfortran, back as far as version 7.4.1, gives the expected output:
a & b are type pvar
T
a & b are type pvar
F
ifort (IFORT) 2021.1 Beta 20201112 gives:
a & b are type pvar
class default: returning false
class default: returning false
F
a & b are type pvar
class default: returning false
class default: returning false
F
This comes about because ifort is using the defined operation to override
the intrinsic uses of the operator as defined in 10.1.5 of the standard.
I believe that gfortran has this one right, since the first paragraph of
15.4.3.4.2 Defined operations has:
"...If the operator is an intrinsic-operator (R608), the number of dummy
arguments shall be consistent with the intrinsic uses of that operator, and
the types, kind type parameters, or ranks of the dummy arguments shall
differ from those required for the intrinsic operation (10.1.5)."
ifort gives the expected result if the interface is moved to the main
program.
Steve, I would be grateful if you would pass this on because my Intel uid
seems to have expired. Of course, your thoughts would be welcome.
The second attachment does away with the select type constructs by
transferring the unlimited polymorphic payloads to deferred length
characters and comparing them. The use of unlimited polymorphic actual
arguments is leading to invalid reads and the loss of 8 bytes in two blocks
because realloc is being finickity about the casting of the arguments.
Also, when u and v carry strings, both storage_size and transfer fail
because the _len field is not used. I will raise PRs on these issues
tomorrow.
Regards
Paul
[-- Attachment #2: equals4.f90 --]
[-- Type: text/x-fortran, Size: 1086 bytes --]
MODULE mytypes
IMPLICIT none
TYPE pvar
character(len=20) :: name
integer :: level
end TYPE pvar
interface operator (==)
module procedure pvar_eq
end interface
contains
function pvar_eq(a,b)
implicit none
class(*), intent(in) ::a,b
logical ::pvar_eq
if (.not. same_type_as (a, b)) then
pvar_eq = .false.
return
end if
select type (a)
type is (pvar)
select type (b)
type is (pvar)
print *, "a & b are type pvar"
if((a%level.eq. b%level) .and. (a%name .eq. b%name)) then
pvar_eq = .true.
else
pvar_eq = .false.
end if
end select
class default
print *, "class default: returning false"
pvar_eq = .false.
end select
end function pvar_eq
end MODULE mytypes
program test_eq
use mytypes
implicit none
type(pvar) x, y
x = pvar('test 1', 100)
y = pvar('test 1', 100)
write(*, *) x == y
x = pvar('test 1', 100)
y = pvar('test 2', 100)
write(*, *) x == y
end program test_eq
[-- Attachment #3: equals5.f90 --]
[-- Type: text/x-fortran, Size: 1156 bytes --]
MODULE mytypes
IMPLICIT none
TYPE pvar
character(len=20) :: name
integer :: level
end TYPE pvar
interface operator (==)
module procedure star_eq
end interface
contains
function star_eq(a,b)
implicit none
class(*), intent(in) ::a,b
character(len=:), allocatable :: c1, c2
logical ::star_eq
integer(8) :: sza, szb
star_eq = same_type_as (a, b)
if (.not. star_eq) return
sza = storage_size (a)/8
szb = storage_size (b)/8
if (sza .ne. szb) then
star_eq = .false.
else
allocate(character(len = sza) :: c1)
allocate(character(len = szb) :: c2)
c1 = transfer (a, c1)
c2 = transfer (b, c2)
star_eq = c1 .eq. c2
end if
end function star_eq
end MODULE mytypes
program test_eq
use mytypes
implicit none
type(pvar) :: x, y
class(*), allocatable :: u, v
x = pvar('test 1', 100)
y = pvar('test 1', 100)
write(*, *) x == y
u = pvar('test 1', 100)
v = pvar('test 2', 100)
write(*, *) u == v
u = 1.0_4
v = 2.0_4
write(*, *) u == v
v = 1.0_4
write(*, *) u == v
deallocate (u,v)
end program test_eq
next reply other threads:[~2021-01-01 16:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-01 16:14 Paul Richard Thomas [this message]
[not found] ` <a23a5712-8381-787e-4583-9ab54bed2a20@stevelionel.com>
2021-01-01 18:31 ` Paul Richard Thomas
2021-01-02 9:45 ` Paul Richard Thomas
2021-01-03 12:22 ` Paul Richard Thomas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAGkQGi+WB-vrx_G=k=V49WGo+orB6a52hAPowB2M1q7TOXpb6Q@mail.gmail.com' \
--to=paul.richard.thomas@gmail.com \
--cc=fortran@gcc.gnu.org \
--cc=steve@stevelionel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).