[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Unexpected gcc diagnostic
From: |
Vadim Zeitlin |
Subject: |
Re: [lmi] Unexpected gcc diagnostic |
Date: |
Wed, 7 Apr 2021 12:27:36 +0200 |
On Wed, 7 Apr 2021 10:00:19 +0000 Greg Chicares <gchicares@sbcglobal.net> wrote:
GC> On 4/6/21 6:59 PM, Greg Chicares wrote:
GC> [...]
GC> >> GC> LMI_ASSERT(Bfts.begin() <= last_bft_in_test_period);
GC> >> GC> LowestBft = *std::min_element(Bfts.begin(),
last_bft_in_test_period);
GC> >
GC> > [...snip my rigorous proof of something that isn't quite what we want...]
GC> >
GC> >> All this is correct and holds even if Bfts vector is empty. However
GC> >> dereferencing the iterator returned by std::min_element() wouldn't be in
GC> >> this case, as it would return non-dereferencable Bfts.end() iterator. I'm
GC> >> not at all sure if it's worth checking for this, but I wanted to at least
GC> >> mention this for completeness.
GC> >
GC> > Thanks: "<=" above isn't good enough; "<" would truly guard
GC> > the "*std::min_element" expression.
GC>
GC> No, I misunderstood.
Thanks for writing this because I thought I was misunderstanding something
myself, as I couldn't see why would the above be the right thing to do and
was going to return to it after getting some sleep as I didn't trust myself
yesterday evening. Admittedly, I didn't get that much sleep, but now it
doesn't matter because you've already confirmed that this didn't work and
so I don't have to explain why I think it wouldn't.
GC> I tried making the change I described above:
GC>
GC> - LMI_ASSERT(Bfts.begin() <= last_bft_in_test_period);
GC> + LMI_ASSERT(Bfts.begin() < last_bft_in_test_period);
GC>
GC> and that caused system-test failures.
GC>
GC> The question is when it's okay to dereference this iterator:
GC> LowestBft = *std::min_element(Bfts.begin(), last_bft_in_test_period);
GC> The answer is not whenever
GC> Bfts.begin() < last_bft_in_test_period
GC> but, rather, whenever both
GC> Bfts.begin() < Bfts.end() [the vector is not empty], and
GC> Bfts.begin() <= last_bft_in_test_period [the range is not insane]
IMO the answer is whenever _either_
Bfts.begin() < last_bft_in_test_period
_or_
last_bft_in_test_period < Bfts.end()
I.e., by construction of last_bft_in_test_period we know that
Bfts.begin() ≤ last_bft_in_test_period ≤ Bfts.end()
and we need at least one of these inequalities to be strict and I would
assert that this is true.
GC> Maybe it's just the aftereffects of yesterday's surgery, but somehow
GC> it troubles me to think that we have different empty sets that have
GC> different minimums: if a≠b, then min [a,a) ≠ min [b,b) .
I don't think it's correct to say that these sets have different minimums.
min_element() returns different iterators for them, but neither of these
iterators can be dereferenced, so the actual value of the minimum is the
same for both empty sets: undefined/undetermined/none.
GC> I guess the explanation is that viewing C++ iterator ranges as
GC> half-open is not rigorous, when I had assumed it was.
I do believe it is and std::min_element() seems perfectly consistent with
the usual C++ convention to me.
Sorry if I'm still missing something here, but I just don't see what is
the problem in all this?
VZ
pgpyWvjf5D2iE.pgp
Description: PGP signature