[llvm] r278397 - [ADT] Add relation operators for Optional

Tim Shen via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 11 13:10:16 PDT 2016


Author: timshen
Date: Thu Aug 11 15:10:15 2016
New Revision: 278397

URL: http://llvm.org/viewvc/llvm-project?rev=278397&view=rev
Log:
[ADT] Add relation operators for Optional

Summary: Make Optional's behavior the same as the coming std::optional.

Reviewers: dblaikie

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D23178

Modified:
    llvm/trunk/include/llvm/ADT/Optional.h
    llvm/trunk/unittests/ADT/OptionalTest.cpp

Modified: llvm/trunk/include/llvm/ADT/Optional.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/Optional.h?rev=278397&r1=278396&r2=278397&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/Optional.h (original)
+++ llvm/trunk/include/llvm/ADT/Optional.h Thu Aug 11 15:10:15 2016
@@ -150,18 +150,43 @@ template <typename T> struct isPodLike<O
   static const bool value = isPodLike<T>::value;
 };
 
-/// \brief Poison comparison between two \c Optional objects. Clients needs to
-/// explicitly compare the underlying values and account for empty \c Optional
-/// objects.
-///
-/// This routine will never be defined. It returns \c void to help diagnose
-/// errors at compile time.
-template<typename T, typename U>
-void operator==(const Optional<T> &X, const Optional<U> &Y);
+template <typename T, typename U>
+bool operator==(const Optional<T> &X, const Optional<U> &Y) {
+  if (X && Y)
+    return *X == *Y;
+  return X.hasValue() == Y.hasValue();
+}
+
+template <typename T, typename U>
+bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
+  return !(X == Y);
+}
+
+template <typename T, typename U>
+bool operator<(const Optional<T> &X, const Optional<U> &Y) {
+  if (X && Y)
+    return *X < *Y;
+  return X.hasValue() < Y.hasValue();
+}
+
+template <typename T, typename U>
+bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
+  return !(Y < X);
+}
+
+template <typename T, typename U>
+bool operator>(const Optional<T> &X, const Optional<U> &Y) {
+  return Y < X;
+}
+
+template <typename T, typename U>
+bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
+  return !(X < Y);
+}
 
 template<typename T>
 bool operator==(const Optional<T> &X, NoneType) {
-  return !X.hasValue();
+  return !X;
 }
 
 template<typename T>
@@ -178,50 +203,86 @@ template<typename T>
 bool operator!=(NoneType, const Optional<T> &X) {
   return X != None;
 }
-/// \brief Poison comparison between two \c Optional objects. Clients needs to
-/// explicitly compare the underlying values and account for empty \c Optional
-/// objects.
-///
-/// This routine will never be defined. It returns \c void to help diagnose
-/// errors at compile time.
-template<typename T, typename U>
-void operator!=(const Optional<T> &X, const Optional<U> &Y);
-
-/// \brief Poison comparison between two \c Optional objects. Clients needs to
-/// explicitly compare the underlying values and account for empty \c Optional
-/// objects.
-///
-/// This routine will never be defined. It returns \c void to help diagnose
-/// errors at compile time.
-template<typename T, typename U>
-void operator<(const Optional<T> &X, const Optional<U> &Y);
-
-/// \brief Poison comparison between two \c Optional objects. Clients needs to
-/// explicitly compare the underlying values and account for empty \c Optional
-/// objects.
-///
-/// This routine will never be defined. It returns \c void to help diagnose
-/// errors at compile time.
-template<typename T, typename U>
-void operator<=(const Optional<T> &X, const Optional<U> &Y);
-
-/// \brief Poison comparison between two \c Optional objects. Clients needs to
-/// explicitly compare the underlying values and account for empty \c Optional
-/// objects.
-///
-/// This routine will never be defined. It returns \c void to help diagnose
-/// errors at compile time.
-template<typename T, typename U>
-void operator>=(const Optional<T> &X, const Optional<U> &Y);
-
-/// \brief Poison comparison between two \c Optional objects. Clients needs to
-/// explicitly compare the underlying values and account for empty \c Optional
-/// objects.
-///
-/// This routine will never be defined. It returns \c void to help diagnose
-/// errors at compile time.
-template<typename T, typename U>
-void operator>(const Optional<T> &X, const Optional<U> &Y);
+
+template <typename T> bool operator<(const Optional<T> &X, NoneType) {
+  return false;
+}
+
+template <typename T> bool operator<(NoneType, const Optional<T> &X) {
+  return X.hasValue();
+}
+
+template <typename T> bool operator<=(const Optional<T> &X, NoneType) {
+  return !(None < X);
+}
+
+template <typename T> bool operator<=(NoneType, const Optional<T> &X) {
+  return !(X < None);
+}
+
+template <typename T> bool operator>(const Optional<T> &X, NoneType) {
+  return None < X;
+}
+
+template <typename T> bool operator>(NoneType, const Optional<T> &X) {
+  return X < None;
+}
+
+template <typename T> bool operator>=(const Optional<T> &X, NoneType) {
+  return None <= X;
+}
+
+template <typename T> bool operator>=(NoneType, const Optional<T> &X) {
+  return X <= None;
+}
+
+template <typename T> bool operator==(const Optional<T> &X, const T &Y) {
+  return X && *X == Y;
+}
+
+template <typename T> bool operator==(const T &X, const Optional<T> &Y) {
+  return Y && X == *Y;
+}
+
+template <typename T> bool operator!=(const Optional<T> &X, const T &Y) {
+  return !(X == Y);
+}
+
+template <typename T> bool operator!=(const T &X, const Optional<T> &Y) {
+  return !(X == Y);
+}
+
+template <typename T> bool operator<(const Optional<T> &X, const T &Y) {
+  return !X || *X < Y;
+}
+
+template <typename T> bool operator<(const T &X, const Optional<T> &Y) {
+  return Y && X < *Y;
+}
+
+template <typename T> bool operator<=(const Optional<T> &X, const T &Y) {
+  return !(Y < X);
+}
+
+template <typename T> bool operator<=(const T &X, const Optional<T> &Y) {
+  return !(Y < X);
+}
+
+template <typename T> bool operator>(const Optional<T> &X, const T &Y) {
+  return Y < X;
+}
+
+template <typename T> bool operator>(const T &X, const Optional<T> &Y) {
+  return Y < X;
+}
+
+template <typename T> bool operator>=(const Optional<T> &X, const T &Y) {
+  return !(X < Y);
+}
+
+template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
+  return !(X < Y);
+}
 
 } // end llvm namespace
 

Modified: llvm/trunk/unittests/ADT/OptionalTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/OptionalTest.cpp?rev=278397&r1=278396&r2=278397&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/OptionalTest.cpp (original)
+++ llvm/trunk/unittests/ADT/OptionalTest.cpp Thu Aug 11 15:10:15 2016
@@ -9,6 +9,7 @@
 
 #include "gtest/gtest.h"
 #include "llvm/ADT/Optional.h"
+
 using namespace llvm;
 
 namespace {
@@ -377,17 +378,144 @@ TEST_F(OptionalTest, MoveGetValueOr) {
 
 #endif // LLVM_HAS_RVALUE_REFERENCE_THIS
 
-TEST_F(OptionalTest, NoneComparison) {
-  Optional<int> o;
-  EXPECT_EQ(o, None);
-  EXPECT_EQ(None, o);
-  EXPECT_FALSE(o != None);
-  EXPECT_FALSE(None != o);
-  o = 3;
-  EXPECT_FALSE(o == None);
-  EXPECT_FALSE(None == o);
-  EXPECT_TRUE(o != None);
-  EXPECT_TRUE(None != o);
+struct EqualTo {
+  template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+    return X == Y;
+  }
+};
+
+struct NotEqualTo {
+  template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+    return X != Y;
+  }
+};
+
+struct Less {
+  template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+    return X < Y;
+  }
+};
+
+struct Greater {
+  template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+    return X > Y;
+  }
+};
+
+struct LessEqual {
+  template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+    return X <= Y;
+  }
+};
+
+struct GreaterEqual {
+  template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+    return X >= Y;
+  }
+};
+
+template <typename OperatorT, typename T>
+void CheckRelation(const Optional<T> &Lhs, const Optional<T> &Rhs,
+                   bool Expected) {
+  EXPECT_EQ(Expected, OperatorT::apply(Lhs, Rhs));
+
+  if (Lhs)
+    EXPECT_EQ(Expected, OperatorT::apply(*Lhs, Rhs));
+  else
+    EXPECT_EQ(Expected, OperatorT::apply(None, Rhs));
+
+  if (Rhs)
+    EXPECT_EQ(Expected, OperatorT::apply(Lhs, *Rhs));
+  else
+    EXPECT_EQ(Expected, OperatorT::apply(Lhs, None));
+}
+
+struct EqualityMock {};
+const Optional<EqualityMock> NoneEq, EqualityLhs((EqualityMock())),
+    EqualityRhs((EqualityMock()));
+bool IsEqual;
+
+bool operator==(const EqualityMock &Lhs, const EqualityMock &Rhs) {
+  EXPECT_EQ(&*EqualityLhs, &Lhs);
+  EXPECT_EQ(&*EqualityRhs, &Rhs);
+  return IsEqual;
+}
+
+TEST_F(OptionalTest, OperatorEqual) {
+  CheckRelation<EqualTo>(NoneEq, NoneEq, true);
+  CheckRelation<EqualTo>(NoneEq, EqualityRhs, false);
+  CheckRelation<EqualTo>(EqualityLhs, NoneEq, false);
+
+  IsEqual = false;
+  CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual);
+  IsEqual = true;
+  CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual);
+}
+
+TEST_F(OptionalTest, OperatorNotEqual) {
+  CheckRelation<NotEqualTo>(NoneEq, NoneEq, false);
+  CheckRelation<NotEqualTo>(NoneEq, EqualityRhs, true);
+  CheckRelation<NotEqualTo>(EqualityLhs, NoneEq, true);
+
+  IsEqual = false;
+  CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual);
+  IsEqual = true;
+  CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual);
+}
+
+struct InequalityMock {};
+const Optional<InequalityMock> NoneIneq, InequalityLhs((InequalityMock())),
+    InequalityRhs((InequalityMock()));
+bool IsLess;
+
+bool operator<(const InequalityMock &Lhs, const InequalityMock &Rhs) {
+  EXPECT_EQ(&*InequalityLhs, &Lhs);
+  EXPECT_EQ(&*InequalityRhs, &Rhs);
+  return IsLess;
+}
+
+TEST_F(OptionalTest, OperatorLess) {
+  CheckRelation<Less>(NoneIneq, NoneIneq, false);
+  CheckRelation<Less>(NoneIneq, InequalityRhs, true);
+  CheckRelation<Less>(InequalityLhs, NoneIneq, false);
+
+  IsLess = false;
+  CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess);
+  IsLess = true;
+  CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess);
+}
+
+TEST_F(OptionalTest, OperatorGreater) {
+  CheckRelation<Greater>(NoneIneq, NoneIneq, false);
+  CheckRelation<Greater>(NoneIneq, InequalityRhs, false);
+  CheckRelation<Greater>(InequalityLhs, NoneIneq, true);
+
+  IsLess = false;
+  CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess);
+  IsLess = true;
+  CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess);
+}
+
+TEST_F(OptionalTest, OperatorLessEqual) {
+  CheckRelation<LessEqual>(NoneIneq, NoneIneq, true);
+  CheckRelation<LessEqual>(NoneIneq, InequalityRhs, true);
+  CheckRelation<LessEqual>(InequalityLhs, NoneIneq, false);
+
+  IsLess = false;
+  CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess);
+  IsLess = true;
+  CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess);
+}
+
+TEST_F(OptionalTest, OperatorGreaterEqual) {
+  CheckRelation<GreaterEqual>(NoneIneq, NoneIneq, true);
+  CheckRelation<GreaterEqual>(NoneIneq, InequalityRhs, false);
+  CheckRelation<GreaterEqual>(InequalityLhs, NoneIneq, true);
+
+  IsLess = false;
+  CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess);
+  IsLess = true;
+  CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess);
 }
 
 } // end anonymous namespace




More information about the llvm-commits mailing list