Make `Has{Equal,Compare,LessThan}` and `With{Equal,Compare}Marker` public.

They are going to be used in other libraries.

PiperOrigin-RevId: 945582542
diff --git a/riegeli/base/compare.h b/riegeli/base/compare.h
index a95d148..66580b3 100644
--- a/riegeli/base/compare.h
+++ b/riegeli/base/compare.h
@@ -213,11 +213,9 @@
   return AsStrongOrdering(a.compare(b));
 }
 
-#endif
+#endif  // !__cpp_impl_three_way_comparison
 
-namespace compare_internal {
-
-#if !__cpp_impl_three_way_comparison
+// `HasEqual<A, B>::value` is `true` if `A == B` is defined.
 
 template <typename A, typename B, typename Enable = void>
 struct HasEqual : std::false_type {};
@@ -228,7 +226,8 @@
     std::void_t<decltype(std::declval<const A&>() == std::declval<const B&>())>>
     : std::true_type {};
 
-#endif
+// `HasCompare<A, B>::value` is `true` if `A <=> B` (C++20) or
+// `RIEGELI_COMPARE(A, B)` (C++17) is defined.
 
 template <typename A, typename B, typename Enable = void>
 struct HasCompare : std::false_type {};
@@ -245,6 +244,19 @@
                           )>> : std::true_type {
 };
 
+// `HasLessThan<A, B>::value` is `true` if `A < B` is defined.
+
+template <typename A, typename B, typename Enable = void>
+struct HasLessThan : std::false_type {};
+
+template <typename A, typename B>
+struct HasLessThan<
+    A, B,
+    std::void_t<decltype(std::declval<const A&>() < std::declval<const B&>())>>
+    : std::true_type {};
+
+namespace compare_internal {
+
 template <typename T, typename Enable = void>
 struct IsDedicatedOrdering : std::false_type {};
 
@@ -270,7 +282,7 @@
 
 // Call `riegeli::Compare(a, b)` instead of C++20 `a <=> b`.
 template <typename A, typename B,
-          std::enable_if_t<compare_internal::HasCompare<A, B>::value, int> = 0>
+          std::enable_if_t<HasCompare<A, B>::value, int> = 0>
 inline auto Compare(const A& a, const B& b) {
 #if __cpp_impl_three_way_comparison
   return a <=> b;
@@ -311,9 +323,23 @@
   return ordering;
 }
 
-#if !__cpp_impl_three_way_comparison
-
-namespace compare_internal {
+// `WithEqualMarker` and `WithCompareMarker` can be used to detect classes
+// relying on `WithEqual` and `WithCompare`.
+//
+// In C++17, a class `T` with comparisons defined using `WithEqual` derives
+// from `WithEqualMarker<T>`, and a class `T` with comparisons defined using
+// `WithCompare` derives from `WithCompareMarker<T>`.
+//
+// `WithEqual` and `WithCompare` provide derived comparison operators with
+// swapped parameters based on available definitions of `operator==` and
+// `RIEGELI_COMPARE()`. If the type of the other parameter in a heterogeneous
+// comparison also relies on `WithEqual` or `WithCompare`, it will provide
+// comparison operators with the same parameter order, with the same meaning.
+// To avoid ambiguity, comparison operators with swapped parameters should be
+// excluded if the type of the other parameter already provides them.
+//
+// This is not an issue in C++20, where swapping parameters is handled on the
+// language level, rather than by providing explicit definitions.
 
 template <typename T>
 class WithEqualMarker {};
@@ -321,11 +347,14 @@
 template <typename T>
 class WithCompareMarker {};
 
+#if !__cpp_impl_three_way_comparison
+
+namespace compare_internal {
+
 template <typename T, typename Other>
 class WithSwappedEqual {
   template <typename DependentT = T,
-            std::enable_if_t<
-                compare_internal::HasEqual<DependentT, Other>::value, int> = 0>
+            std::enable_if_t<HasEqual<DependentT, Other>::value, int> = 0>
   friend bool operator==(const Other& a, const T& b) {
     return b == a;
   }
@@ -333,10 +362,8 @@
 
 template <typename T, typename Other>
 class WithSwappedCompare {
-  template <
-      typename DependentT = T,
-      std::enable_if_t<compare_internal::HasCompare<DependentT, Other>::value,
-                       int> = 0>
+  template <typename DependentT = T,
+            std::enable_if_t<HasCompare<DependentT, Other>::value, int> = 0>
   friend auto RIEGELI_COMPARE(const Other& a, const T& b) {
     return NegateOrdering(RIEGELI_COMPARE(b, a));
   }
@@ -344,7 +371,7 @@
 
 }  // namespace compare_internal
 
-#endif
+#endif  // !__cpp_impl_three_way_comparison
 
 // In C++17, `WithEqual` emulates C++20 rules of rewriting `!=` from `==`,
 // and swapping parameters in heterogeneous `==` and `!=`. Since C++20 it has
@@ -363,20 +390,19 @@
 // If the other parameter does not have a concrete type because the `==` is
 // a template over several other types, do not add a template parameter of
 // `WithEqual`. Instead, define also `==` with swapped parameters, wrapped in
-// `#if !__cpp_impl_three_way_comparison`.
+// `#if !__cpp_impl_three_way_comparison`, and excluded if the other parameter
+// type derives from `WithEqualMarker<Other>`.
 template <typename T, typename... Others>
 class WithEqual
 #if !__cpp_impl_three_way_comparison
-    : public compare_internal::WithEqualMarker<T>,
+    : public WithEqualMarker<T>,
       public compare_internal::WithSwappedEqual<T, Others>...
 #endif
 {
  public:
 #if !__cpp_impl_three_way_comparison
-  template <
-      typename DependentT = T,
-      std::enable_if_t<
-          compare_internal::HasEqual<DependentT, DependentT>::value, int> = 0>
+  template <typename DependentT = T,
+            std::enable_if_t<HasEqual<DependentT, DependentT>::value, int> = 0>
   friend bool operator!=(const T& a, const T& b) {
     return !(a == b);
   }
@@ -384,24 +410,23 @@
   template <
       typename Other,
       std::enable_if_t<std::conjunction_v<std::negation<std::is_same<T, Other>>,
-                                          compare_internal::HasEqual<T, Other>>,
+                                          HasEqual<T, Other>>,
                        int> = 0>
   friend bool operator!=(const T& a, const Other& b) {
     return !(a == b);
   }
 
-  template <typename Other,
-            std::enable_if_t<
-                std::conjunction_v<
-                    std::negation<std::is_same<Other, T>>,
-                    std::negation<std::is_base_of<
-                        compare_internal::WithEqualMarker<Other>, Other>>,
-                    compare_internal::HasEqual<Other, T>>,
-                int> = 0>
+  template <
+      typename Other,
+      std::enable_if_t<std::conjunction_v<std::negation<std::is_same<Other, T>>,
+                                          std::negation<std::is_base_of<
+                                              WithEqualMarker<Other>, Other>>,
+                                          HasEqual<Other, T>>,
+                       int> = 0>
   friend bool operator!=(const Other& a, const T& b) {
     return !(a == b);
   }
-#endif
+#endif  // !__cpp_impl_three_way_comparison
 };
 
 // In C++17, `WithCompare` emulates C++20 rules of rewriting `<`, `>`, `<=`,
@@ -415,7 +440,7 @@
 class WithCompare : public WithEqual<T, Others...>
 #if !__cpp_impl_three_way_comparison
     ,
-                    public compare_internal::WithCompareMarker<T>,
+                    public WithCompareMarker<T>,
                     public compare_internal::WithSwappedCompare<T, Others>...
 #endif
 {
@@ -423,62 +448,58 @@
 #if !__cpp_impl_three_way_comparison
   template <
       typename DependentT = T,
-      std::enable_if_t<
-          compare_internal::HasCompare<DependentT, DependentT>::value, int> = 0>
+      std::enable_if_t<HasCompare<DependentT, DependentT>::value, int> = 0>
   friend bool operator<(const T& a, const T& b) {
     return RIEGELI_COMPARE(a, b) < 0;
   }
   template <
       typename DependentT = T,
-      std::enable_if_t<
-          compare_internal::HasCompare<DependentT, DependentT>::value, int> = 0>
+      std::enable_if_t<HasCompare<DependentT, DependentT>::value, int> = 0>
   friend bool operator>(const T& a, const T& b) {
     return RIEGELI_COMPARE(a, b) > 0;
   }
   template <
       typename DependentT = T,
-      std::enable_if_t<
-          compare_internal::HasCompare<DependentT, DependentT>::value, int> = 0>
+      std::enable_if_t<HasCompare<DependentT, DependentT>::value, int> = 0>
   friend bool operator<=(const T& a, const T& b) {
     return RIEGELI_COMPARE(a, b) <= 0;
   }
   template <
       typename DependentT = T,
-      std::enable_if_t<
-          compare_internal::HasCompare<DependentT, DependentT>::value, int> = 0>
+      std::enable_if_t<HasCompare<DependentT, DependentT>::value, int> = 0>
   friend bool operator>=(const T& a, const T& b) {
     return RIEGELI_COMPARE(a, b) >= 0;
   }
 
-  template <typename Other,
-            std::enable_if_t<
-                std::conjunction_v<std::negation<std::is_same<T, Other>>,
-                                   compare_internal::HasCompare<T, Other>>,
-                int> = 0>
+  template <
+      typename Other,
+      std::enable_if_t<std::conjunction_v<std::negation<std::is_same<T, Other>>,
+                                          HasCompare<T, Other>>,
+                       int> = 0>
   friend bool operator<(const T& a, const Other& b) {
     return RIEGELI_COMPARE(a, b) < 0;
   }
-  template <typename Other,
-            std::enable_if_t<
-                std::conjunction_v<std::negation<std::is_same<T, Other>>,
-                                   compare_internal::HasCompare<T, Other>>,
-                int> = 0>
+  template <
+      typename Other,
+      std::enable_if_t<std::conjunction_v<std::negation<std::is_same<T, Other>>,
+                                          HasCompare<T, Other>>,
+                       int> = 0>
   friend bool operator>(const T& a, const Other& b) {
     return RIEGELI_COMPARE(a, b) > 0;
   }
-  template <typename Other,
-            std::enable_if_t<
-                std::conjunction_v<std::negation<std::is_same<T, Other>>,
-                                   compare_internal::HasCompare<T, Other>>,
-                int> = 0>
+  template <
+      typename Other,
+      std::enable_if_t<std::conjunction_v<std::negation<std::is_same<T, Other>>,
+                                          HasCompare<T, Other>>,
+                       int> = 0>
   friend bool operator<=(const T& a, const Other& b) {
     return RIEGELI_COMPARE(a, b) <= 0;
   }
-  template <typename Other,
-            std::enable_if_t<
-                std::conjunction_v<std::negation<std::is_same<T, Other>>,
-                                   compare_internal::HasCompare<T, Other>>,
-                int> = 0>
+  template <
+      typename Other,
+      std::enable_if_t<std::conjunction_v<std::negation<std::is_same<T, Other>>,
+                                          HasCompare<T, Other>>,
+                       int> = 0>
   friend bool operator>=(const T& a, const Other& b) {
     return RIEGELI_COMPARE(a, b) >= 0;
   }
@@ -489,7 +510,7 @@
                     std::negation<std::is_same<Other, T>>,
                     std::negation<std::is_base_of<
                         compare_internal::WithCompareMarker<Other>, Other>>,
-                    compare_internal::HasCompare<Other, T>>,
+                    HasCompare<Other, T>>,
                 int> = 0>
   friend bool operator<(const Other& a, const T& b) {
     return RIEGELI_COMPARE(a, b) < 0;
@@ -500,7 +521,7 @@
                     std::negation<std::is_same<Other, T>>,
                     std::negation<std::is_base_of<
                         compare_internal::WithCompareMarker<Other>, Other>>,
-                    compare_internal::HasCompare<Other, T>>,
+                    HasCompare<Other, T>>,
                 int> = 0>
   friend bool operator>(const Other& a, const T& b) {
     return RIEGELI_COMPARE(a, b) > 0;
@@ -511,7 +532,7 @@
                     std::negation<std::is_same<Other, T>>,
                     std::negation<std::is_base_of<
                         compare_internal::WithCompareMarker<Other>, Other>>,
-                    compare_internal::HasCompare<Other, T>>,
+                    HasCompare<Other, T>>,
                 int> = 0>
   friend bool operator<=(const Other& a, const T& b) {
     return RIEGELI_COMPARE(a, b) <= 0;
@@ -522,12 +543,12 @@
                     std::negation<std::is_same<Other, T>>,
                     std::negation<std::is_base_of<
                         compare_internal::WithCompareMarker<Other>, Other>>,
-                    compare_internal::HasCompare<Other, T>>,
+                    HasCompare<Other, T>>,
                 int> = 0>
   friend bool operator>=(const Other& a, const T& b) {
     return RIEGELI_COMPARE(a, b) >= 0;
   }
-#endif
+#endif  // !__cpp_impl_three_way_comparison
 };
 
 }  // namespace riegeli