Heterogeneous comparisons
authorNick Terrell <terrelln@fb.com>
Wed, 24 May 2017 02:35:39 +0000 (19:35 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 24 May 2017 02:53:36 +0000 (19:53 -0700)
Summary:
`std::optional` allows heterogeneous comparisons, so `folly::Optional` should as well.
This allows numerical comparisons between different types, like `size_t` and `uint64_t`.

Fixes https://github.com/facebook/folly/issues/602.

Reviewed By: AsyncDBConnMarkedDownDBException

Differential Revision: D5110651

fbshipit-source-id: 34f3368283953033fbb2423ab30b04e38b5b7974

folly/Optional.h
folly/test/OptionalTest.cpp

index 6b49f1ab3b3a7507e3b16ad352e95f75b154e729..16cf86a10090d75575749c34fbad902f4c47d83f 100644 (file)
@@ -359,57 +359,57 @@ Opt make_optional(T&& v) {
 ///////////////////////////////////////////////////////////////////////////////
 // Comparisons.
 
-template<class V>
-bool operator==(const Optional<V>& a, const V& b) {
+template <class U, class V>
+bool operator==(const Optional<U>& a, const V& b) {
   return a.hasValue() && a.value() == b;
 }
 
-template<class V>
-bool operator!=(const Optional<V>& a, const V& b) {
+template <class U, class V>
+bool operator!=(const Optional<U>& a, const V& b) {
   return !(a == b);
 }
 
-template<class V>
-bool operator==(const V& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator==(const U& a, const Optional<V>& b) {
   return b.hasValue() && b.value() == a;
 }
 
-template<class V>
-bool operator!=(const V& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator!=(const U& a, const Optional<V>& b) {
   return !(a == b);
 }
 
-template<class V>
-bool operator==(const Optional<V>& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator==(const Optional<U>& a, const Optional<V>& b) {
   if (a.hasValue() != b.hasValue()) { return false; }
   if (a.hasValue())                 { return a.value() == b.value(); }
   return true;
 }
 
-template<class V>
-bool operator!=(const Optional<V>& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator!=(const Optional<U>& a, const Optional<V>& b) {
   return !(a == b);
 }
 
-template<class V>
-bool operator< (const Optional<V>& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator<(const Optional<U>& a, const Optional<V>& b) {
   if (a.hasValue() != b.hasValue()) { return a.hasValue() < b.hasValue(); }
   if (a.hasValue())                 { return a.value()    < b.value(); }
   return false;
 }
 
-template<class V>
-bool operator> (const Optional<V>& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator>(const Optional<U>& a, const Optional<V>& b) {
   return b < a;
 }
 
-template<class V>
-bool operator<=(const Optional<V>& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator<=(const Optional<U>& a, const Optional<V>& b) {
   return !(b < a);
 }
 
-template<class V>
-bool operator>=(const Optional<V>& a, const Optional<V>& b) {
+template <class U, class V>
+bool operator>=(const Optional<U>& a, const Optional<V>& b) {
   return !(a < b);
 }
 
index b7484dfa978b6488050eab02470ad15982ea9f67..5243e5e55a44388c48223a1e5db3e76e3df8688f 100644 (file)
@@ -372,6 +372,67 @@ TEST(Optional, Comparisons) {
   EXPECT_FALSE(bob != false);
 }
 
+TEST(Optional, HeterogeneousComparisons) {
+  using opt8 = Optional<uint8_t>;
+  using opt64 = Optional<uint64_t>;
+
+  EXPECT_TRUE(opt8(4) == uint64_t(4));
+  EXPECT_FALSE(opt8(8) == uint64_t(4));
+  EXPECT_FALSE(opt8() == uint64_t(4));
+
+  EXPECT_TRUE(uint64_t(4) == opt8(4));
+  EXPECT_FALSE(uint64_t(4) == opt8(8));
+  EXPECT_FALSE(uint64_t(4) == opt8());
+
+  EXPECT_FALSE(opt8(4) != uint64_t(4));
+  EXPECT_TRUE(opt8(8) != uint64_t(4));
+  EXPECT_TRUE(opt8() != uint64_t(4));
+
+  EXPECT_FALSE(uint64_t(4) != opt8(4));
+  EXPECT_TRUE(uint64_t(4) != opt8(8));
+  EXPECT_TRUE(uint64_t(4) != opt8());
+
+  EXPECT_TRUE(opt8() == opt64());
+  EXPECT_TRUE(opt8(4) == opt64(4));
+  EXPECT_FALSE(opt8(8) == opt64(4));
+  EXPECT_FALSE(opt8() == opt64(4));
+  EXPECT_FALSE(opt8(4) == opt64());
+
+  EXPECT_FALSE(opt8() != opt64());
+  EXPECT_FALSE(opt8(4) != opt64(4));
+  EXPECT_TRUE(opt8(8) != opt64(4));
+  EXPECT_TRUE(opt8() != opt64(4));
+  EXPECT_TRUE(opt8(4) != opt64());
+
+  EXPECT_TRUE(opt8() < opt64(4));
+  EXPECT_TRUE(opt8(4) < opt64(8));
+  EXPECT_FALSE(opt8() < opt64());
+  EXPECT_FALSE(opt8(4) < opt64(4));
+  EXPECT_FALSE(opt8(8) < opt64(4));
+  EXPECT_FALSE(opt8(4) < opt64());
+
+  EXPECT_FALSE(opt8() > opt64(4));
+  EXPECT_FALSE(opt8(4) > opt64(8));
+  EXPECT_FALSE(opt8() > opt64());
+  EXPECT_FALSE(opt8(4) > opt64(4));
+  EXPECT_TRUE(opt8(8) > opt64(4));
+  EXPECT_TRUE(opt8(4) > opt64());
+
+  EXPECT_TRUE(opt8() <= opt64(4));
+  EXPECT_TRUE(opt8(4) <= opt64(8));
+  EXPECT_TRUE(opt8() <= opt64());
+  EXPECT_TRUE(opt8(4) <= opt64(4));
+  EXPECT_FALSE(opt8(8) <= opt64(4));
+  EXPECT_FALSE(opt8(4) <= opt64());
+
+  EXPECT_FALSE(opt8() >= opt64(4));
+  EXPECT_FALSE(opt8(4) >= opt64(8));
+  EXPECT_TRUE(opt8() >= opt64());
+  EXPECT_TRUE(opt8(4) >= opt64(4));
+  EXPECT_TRUE(opt8(8) >= opt64(4));
+  EXPECT_TRUE(opt8(4) >= opt64());
+}
+
 TEST(Optional, Conversions) {
   Optional<bool> mbool;
   Optional<short> mshort;