On Wed, 27 Aug 2025 at 16:00, 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 }); > > That would allow us to remove the _Ncmp type and the corresponding > partial_ordering constructor. > > I think that could be just as clear and expressive as using > _Ncmp::unordered, if we add a a suitable comment on the definition of > the constant explaining that we use the most negative value for the > unordered case.
This wouldn't remove the problem of users reflecting the constructor parameter, because they would still be able to observe the _Ord type that way. But I don't think that's a problem we need to care about. The point of doing it would just be to remove an enumeration type and enumerator that are only used in exactly one place.