allow comparing Optional<T> with none
authorNick Wolchko <nwolchko@fb.com>
Mon, 14 Aug 2017 19:49:06 +0000 (12:49 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 14 Aug 2017 19:51:29 +0000 (12:51 -0700)
Summary:
`std::optional` supports comparing with `std::nullopt`, so
`folly::Optional` should do the same with `folly::none`.
This also involves marking hasValue() noexcept to be the same as `std::optional`.

Reviewed By: yfeldblum, WillerZ

Differential Revision: D5617825

fbshipit-source-id: a4b863dd61c3a86223fb21a5b7759e7c295fd272

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

index f8d39cb8cc39e0ce9b4407041e5a9d329be7e825..049251baca9f47fa5cd4696cc45458bc19bd57c1 100644 (file)
@@ -228,11 +228,11 @@ class Optional {
   }
   Value* get_pointer() && = delete;
 
-  bool hasValue() const {
+  bool hasValue() const noexcept {
     return storage_.hasValue();
   }
 
-  explicit operator bool() const {
+  explicit operator bool() const noexcept {
     return hasValue();
   }
 
@@ -319,7 +319,7 @@ class Optional {
                        std::is_trivially_destructible<Value>::value,
                        StorageTriviallyDestructible,
                        StorageNonTriviallyDestructible>::type {
-    bool hasValue() const {
+    bool hasValue() const noexcept {
       return this->hasValue_;
     }
 
@@ -461,6 +461,48 @@ bool operator>=(const V& other, const Optional<V>&) = delete;
 template <class V>
 bool operator>(const V& other, const Optional<V>&) = delete;
 
+// Comparisons with none
+template <class V>
+bool operator==(const Optional<V>& a, None) noexcept {
+  return !a.hasValue();
+}
+template <class V>
+bool operator==(None, const Optional<V>& a) noexcept {
+  return !a.hasValue();
+}
+template <class V>
+bool operator<(const Optional<V>&, None) noexcept {
+  return false;
+}
+template <class V>
+bool operator<(None, const Optional<V>& a) noexcept {
+  return a.hasValue();
+}
+template <class V>
+bool operator>(const Optional<V>& a, None) noexcept {
+  return a.hasValue();
+}
+template <class V>
+bool operator>(None, const Optional<V>&) noexcept {
+  return false;
+}
+template <class V>
+bool operator<=(None, const Optional<V>&) noexcept {
+  return true;
+}
+template <class V>
+bool operator<=(const Optional<V>& a, None) noexcept {
+  return !a.hasValue();
+}
+template <class V>
+bool operator>=(const Optional<V>&, None) noexcept {
+  return true;
+}
+template <class V>
+bool operator>=(None, const Optional<V>& a) noexcept {
+  return !a.hasValue();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 } // namespace folly
index 365d8e41d4c7a9a944effaa8198fc071a31cb011..990f1e17027d74f56b4b33c41b6ef86cea64e67f 100644 (file)
@@ -450,6 +450,39 @@ TEST(Optional, HeterogeneousComparisons) {
   EXPECT_TRUE(opt8(4) >= opt64());
 }
 
+TEST(Optional, NoneComparisons) {
+  using opt = Optional<int>;
+  EXPECT_TRUE(opt() == none);
+  EXPECT_TRUE(none == opt());
+  EXPECT_FALSE(opt(1) == none);
+  EXPECT_FALSE(none == opt(1));
+
+  EXPECT_FALSE(opt() != none);
+  EXPECT_FALSE(none != opt());
+  EXPECT_TRUE(opt(1) != none);
+  EXPECT_TRUE(none != opt(1));
+
+  EXPECT_FALSE(opt() < none);
+  EXPECT_FALSE(none < opt());
+  EXPECT_FALSE(opt(1) < none);
+  EXPECT_TRUE(none < opt(1));
+
+  EXPECT_FALSE(opt() > none);
+  EXPECT_FALSE(none > opt());
+  EXPECT_FALSE(none > opt(1));
+  EXPECT_TRUE(opt(1) > none);
+
+  EXPECT_TRUE(opt() <= none);
+  EXPECT_TRUE(none <= opt());
+  EXPECT_FALSE(opt(1) <= none);
+  EXPECT_TRUE(none <= opt(1));
+
+  EXPECT_TRUE(opt() >= none);
+  EXPECT_TRUE(none >= opt());
+  EXPECT_TRUE(opt(1) >= none);
+  EXPECT_FALSE(none >= opt(1));
+}
+
 TEST(Optional, Conversions) {
   Optional<bool> mbool;
   Optional<short> mshort;