On Thu, 28 Aug 2025 at 11:13, Tomasz Kamiński <tkami...@redhat.com> wrote:
>
> This patch adds two new internal helpers for ordering types:
> * __cmp_cat::__ord to retrieve an internal _Ord value,
> * __cmp_cat::__make<Ordering> to create an ordering from an _Ord value.
>
> Conversions between ordering types are now handled by __cmp_cat::__make. As a
> result, ordering types no longer need to befriend each other, only the new
> helpers.
>
> The __fp_weak_ordering implementation has also been simplified by:
> * using the new helpers to convert partial_ordering to weak_ordering,
> * using strong_ordering to weak_ordering conversion operator,
>   for the __isnan_sign comparison,
> * removing the unused __cat local variable.
>
> Finally, the _Ncmp enum is removed, and the unordered enumerator is added
> to the existing _Ord enum.
>
> libstdc++-v3/ChangeLog:
>
>         * libsupc++/compare (__cmp_cat::_Ord): Add unordered enumerator.
>         (__cmp_cat::_Ncmp): Remove.
>         (__cmp_cat::__ord, __cmp_cat::__make):  Define.
>         (partial_ordering::partial_ordering(__cmp_cat::_Ncmp)): Remove.
>         (operator<=>(__cmp_cat::__unspec, partial_ordering))
>         (partial_ordering::unordered): Replace _Ncmp with _Ord.
>         (std::partial_ordering, std::weak_ordering, std::strong_ordering):
>         Befriend __ord and __make helpers, remove friend declartions for
>         other orderings.
>         (__compare::__fp_weak_ordering): Remove unused __cat variable.
>         Simplify ordering conversions.
> ---
> I bundled the removal of _N_cmp and putting unordered in _Ord here,
> it is related, as new helpers now cleary can operate with one enumerator.
>
> Tested on x86_64-linux locally. Testing on powerpc64le.
> OK for trunk?
>
>  libstdc++-v3/libsupc++/compare | 79 +++++++++++++++-------------------
>  1 file changed, 35 insertions(+), 44 deletions(-)
>
> diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
> index ef0f0376964..7722e205190 100644
> --- a/libstdc++-v3/libsupc++/compare
> +++ b/libstdc++-v3/libsupc++/compare
> @@ -54,9 +54,24 @@ namespace std _GLIBCXX_VISIBILITY(default)
>    {
>      using type = signed char;
>
> -    enum class _Ord : type { equivalent = 0, less = -1, greater = 1 };
> +    enum class _Ord : type
> +    {
> +      equivalent = 0, less = -1, greater = 1,
> +      // value remains unchanged when negated
> +      unordered = -__SCHAR_MAX__ - 1
> +    };
>
> -    enum class _Ncmp : type { unordered = -__SCHAR_MAX__ - 1 };
> +    template<typename _Ordering>
> +      [[__gnu__::__always_inline__]]
> +      constexpr _Ord
> +      __ord(_Ordering __o)
> +      { return _Ord(__o._M_value); }
> +
> +    template<typename _Ordering>
> +      [[__gnu__::__always_inline__]]
> +      constexpr _Ordering
> +      __make(_Ord __o)
> +      { return _Ordering(__o); }

I think we might as well add noexcept to these helper functions. The
constructors that use them are noexcept already, and it might mean
Clang doesn't add a try-catch to those constructors.

OK with that change.

>
>      struct __unspec
>      {
> @@ -74,22 +89,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
>      : _M_value(__cmp_cat::type(__v))
>      { }
>
> -    constexpr explicit
> -    partial_ordering(__cmp_cat::_Ncmp __v) noexcept
> -    : _M_value(__cmp_cat::type(__v))
> -    { }
> -
> -    friend class weak_ordering;
> -    friend class strong_ordering;
> -
>      [[__gnu__::__always_inline__]]
>      constexpr __cmp_cat::type
>      _M_reverse() const
>      {
> -      // leaves _Ncmp::unordered unchanged
> +      // leaves _Ord::unordered unchanged
>        return static_cast<__cmp_cat::type>(-_M_value);
>      }
>
> +    friend constexpr __cmp_cat::_Ord __cmp_cat::__ord<>(partial_ordering);
> +    friend constexpr partial_ordering __cmp_cat::__make<>(__cmp_cat::_Ord);
> +
>    public:
>      // valid values
>      static const partial_ordering less;
> @@ -155,7 +165,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
>      [[nodiscard]]
>      friend constexpr partial_ordering
>      operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept
> -    { return partial_ordering(__cmp_cat::_Ncmp(__v._M_reverse())); }
> +    { return partial_ordering(__cmp_cat::_Ord(__v._M_reverse())); }
>    };
>
>    // valid values' definitions
> @@ -169,7 +179,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
>    partial_ordering::greater(__cmp_cat::_Ord::greater);
>
>    inline constexpr partial_ordering
> -  partial_ordering::unordered(__cmp_cat::_Ncmp::unordered);
> +  partial_ordering::unordered(__cmp_cat::_Ord::unordered);
>
>    class weak_ordering
>    {
> @@ -179,7 +189,8 @@ namespace std _GLIBCXX_VISIBILITY(default)
>      weak_ordering(__cmp_cat::_Ord __v) noexcept : 
> _M_value(__cmp_cat::type(__v))
>      { }
>
> -    friend class strong_ordering;
> +    friend constexpr __cmp_cat::_Ord __cmp_cat::__ord<>(weak_ordering);
> +    friend constexpr weak_ordering __cmp_cat::__make<>(__cmp_cat::_Ord);
>
>    public:
>      // valid values
> @@ -189,7 +200,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
>
>      [[nodiscard]]
>      constexpr operator partial_ordering() const noexcept
> -    { return partial_ordering(__cmp_cat::_Ord(_M_value)); }
> +    { return __cmp_cat::__make<partial_ordering>(__cmp_cat::_Ord(_M_value)); 
> }
>
>      // comparisons
>      [[nodiscard]]
> @@ -271,6 +282,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
>      : _M_value(__cmp_cat::type(__v))
>      { }
>
> +    friend constexpr __cmp_cat::_Ord __cmp_cat::__ord<>(strong_ordering);
> +    friend constexpr strong_ordering __cmp_cat::__make<>(__cmp_cat::_Ord);
> +
>    public:
>      // valid values
>      static const strong_ordering less;
> @@ -280,11 +294,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
>
>      [[nodiscard]]
>      constexpr operator partial_ordering() const noexcept
> -    { return partial_ordering(__cmp_cat::_Ord(_M_value)); }
> +    { return __cmp_cat::__make<partial_ordering>(__cmp_cat::_Ord(_M_value)); 
> }
>
>      [[nodiscard]]
>      constexpr operator weak_ordering() const noexcept
> -    { return weak_ordering(__cmp_cat::_Ord(_M_value)); }
> +    { return __cmp_cat::__make<weak_ordering>(__cmp_cat::_Ord(_M_value)); }
>
>      // comparisons
>      [[nodiscard]]
> @@ -584,26 +598,9 @@ namespace std _GLIBCXX_VISIBILITY(default)
>        constexpr weak_ordering
>        __fp_weak_ordering(_Tp __e, _Tp __f)
>        {
> -       // Returns an integer with the same sign as the argument, and 
> magnitude
> -       // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5
> -       auto __cat = [](_Tp __fp) -> int {
> -         const int __sign = __builtin_signbit(__fp) ? -1 : 1;
> -         if (__builtin_isnormal(__fp))
> -           return (__fp == 0 ? 1 : 3) * __sign;
> -         if (__builtin_isnan(__fp))
> -           return 5 * __sign;
> -         if (int __inf = __builtin_isinf_sign(__fp))
> -           return 4 * __inf;
> -         return 2 * __sign;
> -       };
> -
> -       auto __po = __e <=> __f;
> -       if (is_lt(__po))
> -         return weak_ordering::less;
> -       else if (is_gt(__po))
> -         return weak_ordering::greater;
> -       else if (__po == partial_ordering::equivalent)
> -         return weak_ordering::equivalent;
> +       auto __po = __cmp_cat::__ord(__e <=> __f);
> +       if (__po != __cmp_cat::_Ord::unordered)
> +         return __cmp_cat::__make<weak_ordering>(__po);
>         else  // unordered, at least one argument is NaN
>           {
>             // return -1 for negative nan, +1 for positive nan, 0 otherwise.
> @@ -612,13 +609,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
>                 ? __builtin_signbit(__fp) ? -1 : 1
>                 : 0;
>             };
> -           auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f);
> -           if (is_eq(__ord))
> -             return weak_ordering::equivalent;
> -           else if (is_lt(__ord))
> -             return weak_ordering::less;
> -           else
> -             return weak_ordering::greater;
> +           return __isnan_sign(__e) <=> __isnan_sign(__f);
>           }
>        }
>
> --
> 2.50.1
>

Reply via email to