On Wed, 27 Aug 2025 at 16:11, Tomasz Kaminski <tkami...@redhat.com> wrote: > > > > On Wed, Aug 27, 2025 at 5:07 PM Tomasz Kaminski <tkami...@redhat.com> wrote: >> >> >> >> On Wed, Aug 27, 2025 at 5:00 PM Jonathan Wakely <jwak...@redhat.com> wrote: >>> >>> On Wed, 27 Aug 2025 at 15:03, Patrick Palka <ppa...@redhat.com> wrote: >>> > >>> > On Wed, 27 Aug 2025, Jonathan Wakely wrote: >>> > >>> > > On Wed, 27 Aug 2025 at 11:05, Tomasz Kamiński <tkami...@redhat.com> >>> > > wrote: >>> > > > >>> > > > For any minimum value of a signed type, its negation (with >>> > > > wraparound) results >>> > > > in the same value, behaving like zero. Representing the unordered >>> > > > result with >>> > > > this minimum value, along with 0 for equal, 1 for greater, and -1 for >>> > > > less >>> > > > in partial_ordering, allows its value to be reversed using unary >>> > > > negation. >>> > > > >>> > > > The operator<=(partial_order, 0) now checks if the reversed value is >>> > > > positive. >>> > > > This works correctly because the unordered value remains unchanged >>> > > > and thus >>> > > > negative. >>> > > > >>> > > > libstdc++-v3/ChangeLog: >>> > > > >>> > > > * libsupc++/compare (_Ncmp::_Unordered): Rename and change >>> > > > the value >>> > > > to minimum value of signed char. >>> > > > (_Ncomp::unordered): Renamed from _Unordered, the name is >>> > > > reserved >>> > > > by partial_ordered::unordered. >>> > > > (partial_ordering::_M_reverse()): Define. >>> > > > (operator<=(partial_ordering, __cmp_cat::__unspec)) >>> > > > (operator>=(__cmp_cat::__unspec, partial_ordering)): >>> > > > Implemented >>> > > > in terms of negated _M_value. >>> > > > (operator>=(partial_ordering, __cmp_cat::__unspec)) >>> > > > (operator<=(__cmp_cat::__unspec, partial_ordering)): Directly >>> > > > compare _M_value, as unordered value is negative. >>> > > > (partial_ordering::unordered): Handle _Ncmp::unoredred rename. >>> > > > --- >>> > > > Changes in v3: >>> > > > * rename and simplify defintion of _Ncmp::unordered >>> > > >>> > > Ah yes, we don't need to use an _Ugly name name for unordered. >>> > >>> > FWIW it wasn't 100% obvious to me that renaming _Unordered to unordered >>> > is safe here, but it does seem to be, since AFAICT there's no way for a >>> > user to refer to the enumeration __cmp_cat::_Ncmp (e.g. via decltype). >>> > >>> > Otherwise it'd potentially be an observable change: >>> > >>> > struct A { >>> > using enum decltype(some-expr-of-type-__cmp_cat::_Ncmp); >>> > int unordered; // now errors due to conflict with _Ncmp::unordered >>> > }; >>> >>> Yeah, that type should never be exposed from any public API, so they >>> need to refer to __cmp_cat::_Ncmp directly, which would obviously mean >>> they're asking to get hurt and they get what they asked for. >>> >>> I suppose they could use reflection to inspect the parameters of the >>> partial_ordering constructor, but that also seems to be a >>> self-inflicted wound. >>> >>> However, do we really need the _Ncmp type and unordered enumerator at all?! >>> >>> We could just define the unordered constant like this: >>> >>> inline constexpr partial_ordering >>> partial_ordering::unordered(__cmp_cat::_Ord{ -__SCHAR_MAX__ - 1 }); >> >> At that point we could put an unordered enumerator into _Ord enum as well, >> which would be my preferred approach. I still think having a list of all used >> in one place have benefits. > > If you agree with that direction (adding unordered to _Ord), pre-approve the > patch > here and I will commit it directly.
Yes, that seems fine. I'm ambivalent about the value of the unordered enumerator, but if you think it's worth keeping it, let's keep it. I was just following the exposition-only types in the standard (in [cmp.categories.pre]) when I added _Ncmp, but I think having separate types is overkill. Users can't use the _Ord type directly anyway, so it doesn't matter if _Ord::unordered exists. So that change is pre-approved for trunk.