Allow WTF::map to use any class that is iterable and has a size getter
[WebKit-https.git] / Source / WTF / wtf / Vector.h
index 2aebe71..4875051 100644 (file)
@@ -1562,34 +1562,49 @@ size_t removeRepeatedElements(Vector<T, inlineCapacity, OverflowHandler, minCapa
     return removeRepeatedElements(vector, [] (T& a, T& b) { return a == b; });
 }
 
     return removeRepeatedElements(vector, [] (T& a, T& b) { return a == b; });
 }
 
-template<typename Transformer, typename SourceType> struct Mapper {
+template<typename MapFunction, typename SourceType>
+struct MapFunctionInspector {
     using RealSourceType = typename std::remove_reference<SourceType>::type;
     using RealSourceType = typename std::remove_reference<SourceType>::type;
-    using SourceItemType = typename RealSourceType::ValueType;
-    using DestinationItemType = typename std::result_of<Transformer(SourceItemType&&)>::type;
+    using IteratorType = decltype(std::begin(std::declval<RealSourceType>()));
+    using SourceItemType = typename std::iterator_traits<IteratorType>::value_type;
+};
+
+template<typename MapFunction, typename SourceType, typename Enable = void>
+struct Mapper {
+    using SourceItemType = typename MapFunctionInspector<MapFunction, SourceType>::SourceItemType;
+    using DestinationItemType = typename std::result_of<MapFunction(SourceItemType&)>::type;
 
 
-    static Vector<DestinationItemType> map(const RealSourceType& source, const Transformer& transformer)
+    static Vector<DestinationItemType> map(SourceType source, const MapFunction& mapFunction)
     {
         Vector<DestinationItemType> result;
     {
         Vector<DestinationItemType> result;
+        // FIXME: Use std::size when available on all compilers.
         result.reserveInitialCapacity(source.size());
         for (auto& item : source)
         result.reserveInitialCapacity(source.size());
         for (auto& item : source)
-            result.uncheckedAppend(transformer(item));
+            result.uncheckedAppend(mapFunction(item));
         return result;
     }
         return result;
     }
+};
+
+template<typename MapFunction, typename SourceType>
+struct Mapper<MapFunction, SourceType, typename std::enable_if<std::is_rvalue_reference<SourceType&&>::value>::type> {
+    using SourceItemType = typename MapFunctionInspector<MapFunction, SourceType>::SourceItemType;
+    using DestinationItemType = typename std::result_of<MapFunction(SourceItemType&&)>::type;
 
 
-    static Vector<DestinationItemType> map(RealSourceType&& source, const Transformer& transformer)
+    static Vector<DestinationItemType> map(SourceType&& source, const MapFunction& mapFunction)
     {
         Vector<DestinationItemType> result;
     {
         Vector<DestinationItemType> result;
+        // FIXME: Use std::size when available on all compilers.
         result.reserveInitialCapacity(source.size());
         for (auto& item : source)
         result.reserveInitialCapacity(source.size());
         for (auto& item : source)
-            result.uncheckedAppend(transformer(std::forward<SourceItemType>(item)));
+            result.uncheckedAppend(mapFunction(WTFMove(item)));
         return result;
     }
 };
 
         return result;
     }
 };
 
-template<typename Transformer, typename VectorType>
-Vector<typename Mapper<Transformer, VectorType>::DestinationItemType> map(VectorType&& source, Transformer&& transformer)
+template<typename MapFunction, typename SourceType>
+Vector<typename Mapper<MapFunction, SourceType>::DestinationItemType> map(SourceType&& source, MapFunction&& mapFunction)
 {
 {
-    return Mapper<Transformer, VectorType>::map(std::forward<VectorType>(source), std::forward<Transformer>(transformer));
+    return Mapper<MapFunction, SourceType>::map(std::forward<SourceType>(source), std::forward<MapFunction>(mapFunction));
 }
 
 } // namespace WTF
 }
 
 } // namespace WTF