UniqueVector::Append() support any iterable container.

A small usability improvement that allows the Append()
method to use any input container. Also supports moving
the input items directly into the vector when possible.

Change-Id: I93c486744e32df5e8dc007368211fe5227552df4
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/13623
Reviewed-by: Sylvain Defresne <sdefresne@chromium.org>
Commit-Queue: David Turner <digit@google.com>
diff --git a/src/gn/unique_vector.h b/src/gn/unique_vector.h
index 0f6994f..473786d 100644
--- a/src/gn/unique_vector.h
+++ b/src/gn/unique_vector.h
@@ -186,11 +186,28 @@
       push_back(*i);
   }
 
-  // Append another vector into this one.
-  void Append(const UniqueVector& other) {
+  // Append from any iterable container with begin() and end()
+  // methods, whose iterators derefence to values convertible to T.
+  template <typename C,
+            typename = std::void_t<
+                decltype(static_cast<const T>(*std::declval<C>().begin())),
+                decltype(static_cast<const T>(*std::declval<C>().end()))>>
+  void Append(const C& other) {
     Append(other.begin(), other.end());
   }
 
+  // Append from any moveable iterable container with begin() and
+  // end() methods. This variant moves items from the container
+  // into the UniqueVector instance.
+  template <typename C,
+            typename = std::void_t<
+                decltype(static_cast<T>(*std::declval<C>().begin())),
+                decltype(static_cast<T>(*std::declval<C>().end()))>>
+  void Append(C&& other) {
+    for (auto it = other.begin(); it != other.end(); ++it)
+      push_back(std::move(*it));
+  }
+
   // Returns true if the item is already in the vector.
   bool Contains(const T& t) const {
     size_t hash;