From cb2bf7c923c1f4d574ed9fb2f2c676801c4e0264 Mon Sep 17 00:00:00 2001
From: Rounak Tibrewal <rounak@fb.com>
Date: Thu, 17 Dec 2020 13:37:43 -0800
Subject: [PATCH] Revert D25549986: De-template Range comparison operators

Differential Revision:
D25549986 (https://github.com/facebook/folly/commit/9a83e4242a933f91c9339b4c6d223267a43a89c1)

Original commit changeset: fd323e2e8cbf

fbshipit-source-id: af2bdb9f66d23d144f7e2e96118727d8b158f83f
---
 folly/Range.h | 136 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 112 insertions(+), 24 deletions(-)

diff --git a/folly/Range.h b/folly/Range.h
index 38deffb3a..e17c64265 100644
--- a/folly/Range.h
+++ b/folly/Range.h
@@ -1066,30 +1066,6 @@ class Range {
     return process(split_step(delimiter), std::forward<Args>(args)...);
   }
 
-  friend bool operator==(const Range& lhs, const Range& rhs) {
-    return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
-  }
-
-  friend bool operator!=(const Range& lhs, const Range& rhs) {
-    return !(operator==(lhs, rhs));
-  }
-
-  friend bool operator<(const Range& lhs, const Range& rhs) {
-    return lhs.compare(rhs) < 0;
-  }
-
-  friend bool operator<=(const Range& lhs, const Range& rhs) {
-    return lhs.compare(rhs) <= 0;
-  }
-
-  friend bool operator>(const Range& lhs, const Range& rhs) {
-    return lhs.compare(rhs) > 0;
-  }
-
-  friend bool operator>=(const Range& lhs, const Range& rhs) {
-    return lhs.compare(rhs) >= 0;
-  }
-
  private:
   Iter b_;
   Iter e_;
@@ -1175,6 +1151,118 @@ std::basic_ostream<C>& operator<<(std::basic_ostream<C>& os, Range<C*> piece) {
   return os;
 }
 
+/**
+ * Templated comparison operators
+ */
+
+template <class Iter>
+inline bool operator==(const Range<Iter>& lhs, const Range<Iter>& rhs) {
+  return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
+}
+
+template <class Iter>
+inline bool operator!=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
+  return !(operator==(lhs, rhs));
+}
+
+template <class Iter>
+inline bool operator<(const Range<Iter>& lhs, const Range<Iter>& rhs) {
+  return lhs.compare(rhs) < 0;
+}
+
+template <class Iter>
+inline bool operator<=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
+  return lhs.compare(rhs) <= 0;
+}
+
+template <class Iter>
+inline bool operator>(const Range<Iter>& lhs, const Range<Iter>& rhs) {
+  return lhs.compare(rhs) > 0;
+}
+
+template <class Iter>
+inline bool operator>=(const Range<Iter>& lhs, const Range<Iter>& rhs) {
+  return lhs.compare(rhs) >= 0;
+}
+
+/**
+ * Specializations of comparison operators for StringPiece
+ */
+
+namespace detail {
+
+template <class A, class B>
+struct ComparableAsStringPiece {
+  enum {
+    value = (std::is_convertible<A, StringPiece>::value &&
+             std::is_same<B, StringPiece>::value) ||
+        (std::is_convertible<B, StringPiece>::value &&
+         std::is_same<A, StringPiece>::value)
+  };
+};
+
+} // namespace detail
+
+/**
+ * operator== through conversion for Range<const char*>
+ */
+template <class T, class U>
+std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator==(
+    const T& lhs,
+    const U& rhs) {
+  return StringPiece(lhs) == StringPiece(rhs);
+}
+
+/**
+ * operator!= through conversion for Range<const char*>
+ */
+template <class T, class U>
+std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator!=(
+    const T& lhs,
+    const U& rhs) {
+  return StringPiece(lhs) != StringPiece(rhs);
+}
+
+/**
+ * operator< through conversion for Range<const char*>
+ */
+template <class T, class U>
+std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator<(
+    const T& lhs,
+    const U& rhs) {
+  return StringPiece(lhs) < StringPiece(rhs);
+}
+
+/**
+ * operator> through conversion for Range<const char*>
+ */
+template <class T, class U>
+std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator>(
+    const T& lhs,
+    const U& rhs) {
+  return StringPiece(lhs) > StringPiece(rhs);
+}
+
+/**
+ * operator< through conversion for Range<const char*>
+ */
+template <class T, class U>
+std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator<=(
+    const T& lhs,
+    const U& rhs) {
+  return StringPiece(lhs) <= StringPiece(rhs);
+}
+
+/**
+ * operator> through conversion for Range<const char*>
+ */
+template <class T, class U>
+std::enable_if_t<detail::ComparableAsStringPiece<T, U>::value, bool> operator>=(
+    const T& lhs,
+    const U& rhs) {
+  return StringPiece(lhs) >= StringPiece(rhs);
+}
+
 /**
  * Finds substrings faster than brute force by borrowing from Boyer-Moore
  */
-- 
2.26.2