From 8bca2fb294ee888e2c9b73123205868c0c947a51 Mon Sep 17 00:00:00 2001 From: Nick Terrell Date: Tue, 23 May 2017 19:35:39 -0700 Subject: [PATCH] Heterogeneous comparisons 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 | 40 ++++++++++++------------ folly/test/OptionalTest.cpp | 61 +++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 20 deletions(-) diff --git a/folly/Optional.h b/folly/Optional.h index 6b49f1ab..16cf86a1 100644 --- a/folly/Optional.h +++ b/folly/Optional.h @@ -359,57 +359,57 @@ Opt make_optional(T&& v) { /////////////////////////////////////////////////////////////////////////////// // Comparisons. -template -bool operator==(const Optional& a, const V& b) { +template +bool operator==(const Optional& a, const V& b) { return a.hasValue() && a.value() == b; } -template -bool operator!=(const Optional& a, const V& b) { +template +bool operator!=(const Optional& a, const V& b) { return !(a == b); } -template -bool operator==(const V& a, const Optional& b) { +template +bool operator==(const U& a, const Optional& b) { return b.hasValue() && b.value() == a; } -template -bool operator!=(const V& a, const Optional& b) { +template +bool operator!=(const U& a, const Optional& b) { return !(a == b); } -template -bool operator==(const Optional& a, const Optional& b) { +template +bool operator==(const Optional& a, const Optional& b) { if (a.hasValue() != b.hasValue()) { return false; } if (a.hasValue()) { return a.value() == b.value(); } return true; } -template -bool operator!=(const Optional& a, const Optional& b) { +template +bool operator!=(const Optional& a, const Optional& b) { return !(a == b); } -template -bool operator< (const Optional& a, const Optional& b) { +template +bool operator<(const Optional& a, const Optional& b) { if (a.hasValue() != b.hasValue()) { return a.hasValue() < b.hasValue(); } if (a.hasValue()) { return a.value() < b.value(); } return false; } -template -bool operator> (const Optional& a, const Optional& b) { +template +bool operator>(const Optional& a, const Optional& b) { return b < a; } -template -bool operator<=(const Optional& a, const Optional& b) { +template +bool operator<=(const Optional& a, const Optional& b) { return !(b < a); } -template -bool operator>=(const Optional& a, const Optional& b) { +template +bool operator>=(const Optional& a, const Optional& b) { return !(a < b); } diff --git a/folly/test/OptionalTest.cpp b/folly/test/OptionalTest.cpp index b7484dfa..5243e5e5 100644 --- a/folly/test/OptionalTest.cpp +++ b/folly/test/OptionalTest.cpp @@ -372,6 +372,67 @@ TEST(Optional, Comparisons) { EXPECT_FALSE(bob != false); } +TEST(Optional, HeterogeneousComparisons) { + using opt8 = Optional; + using opt64 = Optional; + + 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 mbool; Optional mshort; -- 2.34.1