Bug 1184839 - Provide an overloaded == operator for mozilla::Variant; r=Waldo
authorNick Fitzgerald <fitzgen@gmail.com>
Sun, 19 Jul 2015 16:32:00 +0200
changeset 253679 53d4da7e97f17007f6595ebea78911c59f83a715
parent 253678 2d52988a5e8389863f20aa33b04f6d4499563ffe
child 253680 06c3e93b647d0e47c990a27f149559fba6781777
push id29074
push userryanvm@gmail.com
push dateMon, 20 Jul 2015 19:51:26 +0000
treeherdermozilla-central@b86e3ab5e974 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1184839
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1184839 - Provide an overloaded == operator for mozilla::Variant; r=Waldo
mfbt/Variant.h
mfbt/tests/TestVariant.cpp
--- a/mfbt/Variant.h
+++ b/mfbt/Variant.h
@@ -109,16 +109,23 @@ struct VariantImplementation<N, T> {
   static void moveConstruct(void* aLhs, Variant&& aRhs) {
     new (aLhs) T(aRhs.template extract<T>());
   }
 
   template<typename Variant>
   static void destroy(Variant& aV) {
     aV.template as<T>().~T();
   }
+
+  template<typename Variant>
+  static bool
+  equal(const Variant& aLhs, const Variant& aRhs)
+  {
+      return aLhs.template as<T>() == aRhs.template as<T>();
+  }
 };
 
 // VariantImplementation for some variant type T.
 template<size_t N, typename T, typename... Ts>
 struct VariantImplementation<N, T, Ts...>
 {
   // The next recursive VariantImplementation.
   using Next = VariantImplementation<N + 1, Ts...>;
@@ -149,16 +156,26 @@ struct VariantImplementation<N, T, Ts...
   template<typename Variant>
   static void destroy(Variant& aV) {
     if (aV.template is<T>()) {
       aV.template as<T>().~T();
     } else {
       Next::destroy(aV);
     }
   }
+
+  template<typename Variant>
+  static bool equal(const Variant& aLhs, const Variant& aRhs) {
+    if (aLhs.template is<T>()) {
+      MOZ_ASSERT(aRhs.template is<T>());
+      return aLhs.template as<T>() == aRhs.template as<T>();
+    } else {
+      return Next::equal(aLhs, aRhs);
+    }
+  }
 };
 
 } // namespace detail
 
 /**
  * # mozilla::Variant
  *
  * A variant / tagged union / heterogenous disjoint union / sum-type template
@@ -309,16 +326,33 @@ public:
   /** Check which variant type is currently contained. */
   template<typename T>
   bool is() const {
     static_assert(detail::IsVariant<T, Ts...>::value,
                   "provided a type not found in this Variant's type list");
     return Impl::template tag<T>() == tag;
   }
 
+  /**
+   * Operator == overload that defers to the variant type's operator==
+   * implementation if the rhs is tagged as the same type as this one.
+   */
+  bool operator==(const Variant& aRhs) const {
+    return tag == aRhs.tag && Impl::equal(*this, aRhs);
+  }
+
+  /**
+   * Operator != overload that defers to the negation of the variant type's
+   * operator== implementation if the rhs is tagged as the same type as this
+   * one.
+   */
+  bool operator!=(const Variant& aRhs) const {
+    return !(*this == aRhs);
+  }
+
   // Accessors for working with the contained variant value.
 
   /** Mutable reference. */
   template<typename T>
   T& as() {
     static_assert(detail::IsVariant<T, Ts...>::value,
                   "provided a type not found in this Variant's type list");
     MOZ_ASSERT(is<T>());
--- a/mfbt/tests/TestVariant.cpp
+++ b/mfbt/tests/TestVariant.cpp
@@ -88,19 +88,50 @@ testDestructor()
     }
 
     MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 1); // v's copy of d is destroyed.
   }
 
   MOZ_RELEASE_ASSERT(Destroyer::destroyedCount == 2); // d is destroyed.
 }
 
+static void
+testEquality()
+{
+  printf("testEquality\n");
+  using V = Variant<char, int>;
+
+  V v0('a');
+  V v1('b');
+  V v2('b');
+  V v3(42);
+  V v4(27);
+  V v5(27);
+  V v6(int('b'));
+
+  MOZ_RELEASE_ASSERT(v0 != v1);
+  MOZ_RELEASE_ASSERT(v1 == v2);
+  MOZ_RELEASE_ASSERT(v2 != v3);
+  MOZ_RELEASE_ASSERT(v3 != v4);
+  MOZ_RELEASE_ASSERT(v4 == v5);
+  MOZ_RELEASE_ASSERT(v1 != v6);
+
+  MOZ_RELEASE_ASSERT(v0 == v0);
+  MOZ_RELEASE_ASSERT(v1 == v1);
+  MOZ_RELEASE_ASSERT(v2 == v2);
+  MOZ_RELEASE_ASSERT(v3 == v3);
+  MOZ_RELEASE_ASSERT(v4 == v4);
+  MOZ_RELEASE_ASSERT(v5 == v5);
+  MOZ_RELEASE_ASSERT(v6 == v6);
+}
+
 int
 main()
 {
   testSimple();
   testCopy();
   testMove();
   testDestructor();
+  testEquality();
 
   printf("TestVariant OK!\n");
   return 0;
 }