Bug 1484373: Part 2a - Add Tuple ForEach helper function. r=froydnj
authorKris Maglione <maglione.k@gmail.com>
Sun, 19 Aug 2018 17:42:59 -0700
changeset 433167 70b72c8bddc6dd189bf6cbc79828b790e032af3e
parent 433166 ddba7fcc0d3b5493f7039d5dd61a77d647cb03f3
child 433168 13e34da7e745043689e2bda3adbc889b25782f71
push id106987
push usermaglione.k@gmail.com
push dateThu, 23 Aug 2018 22:05:51 +0000
treeherdermozilla-inbound@b88f5fa7dca4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1484373
milestone63.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 1484373: Part 2a - Add Tuple ForEach helper function. r=froydnj It's currently fairly difficult to perform some operation on each member of a tuple. This is a particular issue in the context of adding a cycle collection helper, where we need to perform traverse and unlink operations on each member of a tuple, and don't have a way to do so without several layers of templates. This patch adds a ForEach function which will call a function on each element of the tuple. This would typically be used with a lambda function with a single `auto&` argument.
mfbt/Tuple.h
--- a/mfbt/Tuple.h
+++ b/mfbt/Tuple.h
@@ -95,16 +95,19 @@ struct TupleImpl;
  * of an empty tuple).
  */
 template<std::size_t Index>
 struct TupleImpl<Index> {
   bool operator==(const TupleImpl<Index>& aOther) const
   {
     return true;
   }
+
+  template <typename F>
+  void ForEach(const F& aFunc) {}
 };
 
 /*
  * One node of the recursive inheritance hierarchy. It stores the element at
  * index 'Index' of a tuple, of type 'HeadT', and inherits from the nodes
  * that store the remaining elements, of types 'TailT...'.
  */
 template<std::size_t Index, typename HeadT, typename... TailT>
@@ -186,16 +189,37 @@ struct TupleImpl<Index, HeadT, TailT...>
     Head(*this) = std::move(Head(aOther));
     Tail(*this) = std::move(Tail(aOther));
     return *this;
   }
   bool operator==(const TupleImpl& aOther) const
   {
     return Head(*this) == Head(aOther) && Tail(*this) == Tail(aOther);
   }
+
+  template <typename F>
+  void ForEach(const F& aFunc) const &
+  {
+    aFunc(Head(*this));
+    Tail(*this).ForEach(aFunc);
+  }
+
+  template <typename F>
+  void ForEach(const F& aFunc) &
+  {
+    aFunc(Head(*this));
+    Tail(*this).ForEach(aFunc);
+  }
+
+  template <typename F>
+  void ForEach(const F& aFunc) &&
+  {
+    aFunc(std::move(Head(*this)));
+    std::move(Tail(*this)).ForEach(aFunc);
+  }
 private:
   HeadT mHead;  // The element stored at this index in the tuple.
 };
 
 } // namespace detail
 
 /**
  * Tuple is a class that stores zero or more objects, whose types are specified
@@ -416,16 +440,60 @@ auto Get(Tuple<Elements...>&& aTuple)
     -> decltype(std::move(mozilla::Get<Index>(aTuple)))
 {
   // We need a 'mozilla::' qualification here to avoid
   // name lookup only finding the current function.
   return std::move(mozilla::Get<Index>(aTuple));
 }
 
 /**
+ * Helpers which call a function for each member of the tuple in turn. This will
+ * typically be used with a lambda function with an `auto&` argument:
+ *
+ *   Tuple<Foo*, Bar*, SmartPtr<Baz>> tuple{a, b, c};
+ *
+ *   ForEach(tuple, [](auto& aElem) {
+ *     aElem = nullptr;
+ *   });
+ */
+
+template <typename F>
+inline void
+ForEach(const Tuple<>& aTuple, const F& aFunc)
+{
+}
+
+template <typename F>
+inline void
+ForEach(Tuple<>& aTuple, const F& aFunc)
+{
+}
+
+template <typename F, typename... Elements>
+void
+ForEach(const Tuple<Elements...>& aTuple, const F& aFunc)
+{
+  aTuple.ForEach(aTuple, aFunc);
+}
+
+template <typename F, typename... Elements>
+void
+ForEach(Tuple<Elements...>& aTuple, const F& aFunc)
+{
+  aTuple.ForEach(aFunc);
+}
+
+template <typename F, typename... Elements>
+void
+ForEach(Tuple<Elements...>&& aTuple, const F& aFunc)
+{
+  std::forward<Tuple<Elements...>>(aTuple).ForEach(aFunc);
+}
+
+/**
  * A convenience function for constructing a tuple out of a sequence of
  * values without specifying the type of the tuple.
  * The type of the tuple is deduced from the types of its elements.
  *
  * Example:
  *
  * auto tuple = MakeTuple(42, 0.5f, 'c');  // has type Tuple<int, float, char>
  */