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.

Reply via email to