include/o3tl/compare.hxx |   26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

New commits:
commit c1991a5fb229161b5f2ad3240afc5b2417abe5c9
Author:     Stephan Bergmann <[email protected]>
AuthorDate: Thu Feb 8 09:53:04 2024 +0100
Commit:     Stephan Bergmann <[email protected]>
CommitDate: Thu Feb 8 22:43:49 2024 +0100

    A better approximation of std::strong_order
    
    (Unfortunately, the environments that don't have std::strong_order typically
    also don't have std::bit_cast, so we need to approximate that, too.)
    
    Change-Id: I0b6344c83bc8227af090cfe68902acd385f682ff
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163111
    Tested-by: Jenkins
    Reviewed-by: Stephan Bergmann <[email protected]>

diff --git a/include/o3tl/compare.hxx b/include/o3tl/compare.hxx
index 27c6b31ac647..2b0db4e5be93 100644
--- a/include/o3tl/compare.hxx
+++ b/include/o3tl/compare.hxx
@@ -12,13 +12,17 @@
 #include <sal/config.h>
 
 #include <compare>
+#include <concepts>
+#include <cstdint>
+#include <cstring>
+#include <limits>
 
 #include <config_global.h>
 
 namespace o3tl
 {
-// A poor approximation of C++20 <compare> std::strong_order, falling back to 
operator <=> (so e.g.
-// not providing a strict weak ordering for floating-point types with NaN):
+// An approximation of C++20 <compare> std::strong_order that should work at 
least for IEC559 float
+// and double on platforms that have correspondingly-sized std::int32_t and 
std::int64_t:
 #if HAVE_CPP_STRONG_ORDER
 
 inline constexpr auto strong_order = std::strong_order;
@@ -27,9 +31,25 @@ inline constexpr auto strong_order = std::strong_order;
 
 namespace detail
 {
+template<typename To, typename From> To bit_cast(From val) requires (sizeof 
(To) == sizeof (From)) {
+    char buf alignas(To)[sizeof (From)];
+    std::memcpy(buf, &val, sizeof (From));
+    return *reinterpret_cast<To const *>(buf);
+}
+
 struct strong_order
 {
-    auto operator()(auto x, auto y) const { return x <=> y; }
+    template <typename T> auto operator ()(T x, T y) const
+        requires std::same_as<T, float> && std::numeric_limits<T>::is_iec559
+    {
+        return bit_cast<std::int32_t>(x) <=> bit_cast<std::int32_t>(y);
+    }
+
+    template <typename T> auto operator ()(T x, T y) const
+        requires std::same_as<T, double> && std::numeric_limits<T>::is_iec559
+    {
+        return bit_cast<std::int64_t>(x) <=> bit_cast<std::int64_t>(y);
+    }
 };
 }
 
  • core.git: include/o3tl Caolán McNamara (via logerrit)
    • core.git: include/o3tl Stephan Bergmann (via logerrit)

Reply via email to