Added folly::hint_emplace_iterator to folly/Iterator.h
[folly.git] / folly / Enumerate.h
index 7d4ae4d03b99763ec26f4e80f0045e46b4a1435c..94bcecefbd647273a059ee2418a524a162fd44ac 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,9 @@
 #include <iterator>
 #include <memory>
 
-/*
+#include <folly/portability/SysTypes.h>
+
+/**
  * Similar to Python's enumerate(), folly::enumerate() can be used to
  * iterate a range with a for-range loop, and it also allows to
  * retrieve the count of iterations so far.
@@ -58,6 +60,18 @@ struct MakeConst<T*> {
   using type = const T*;
 };
 
+// Raw pointers don't have an operator->() member function, so the
+// second overload will be SFINAEd out in that case. Otherwise, the
+// second is preferred in the partial order for getPointer(_, 0).
+template <class Iterator>
+auto getPointer(const Iterator& it, long) -> decltype(std::addressof(*it)) {
+  return std::addressof(*it);
+}
+template <class Iterator>
+auto getPointer(const Iterator& it, int) -> decltype(it.operator->()) {
+  return it.operator->();
+}
+
 template <class Iterator>
 class Enumerator {
  public:
@@ -78,7 +92,7 @@ class Enumerator {
       return *it_;
     }
     pointer operator->() {
-      return std::addressof(**this);
+      return getPointer(it_, 0);
     }
 
     // Const Proxy: Force const references.
@@ -86,7 +100,7 @@ class Enumerator {
       return *it_;
     }
     typename MakeConst<pointer>::type operator->() const {
-      return std::addressof(**this);
+      return getPointer(it_, 0);
     }
 
    private:
@@ -106,15 +120,20 @@ class Enumerator {
     return *this;
   }
 
-  bool operator==(const Enumerator& rhs) {
+  template <typename OtherIterator>
+  bool operator==(const Enumerator<OtherIterator>& rhs) {
     return it_ == rhs.it_;
   }
 
-  bool operator!=(const Enumerator& rhs) {
+  template <typename OtherIterator>
+  bool operator!=(const Enumerator<OtherIterator>& rhs) {
     return !(*this == rhs);
   }
 
  private:
+  template <typename OtherIterator>
+  friend class Enumerator;
+
   Iterator it_;
   size_t idx_ = 0;
 };
@@ -122,16 +141,17 @@ class Enumerator {
 template <class Range>
 class RangeEnumerator {
   Range r_;
-  using Iterator = decltype(r_.begin());
+  using BeginIteratorType = decltype(std::declval<Range>().begin());
+  using EndIteratorType = decltype(std::declval<Range>().end());
 
  public:
   explicit RangeEnumerator(Range&& r) : r_(std::forward<Range>(r)) {}
 
-  Enumerator<Iterator> begin() {
-    return Enumerator<Iterator>(r_.begin());
+  Enumerator<BeginIteratorType> begin() {
+    return Enumerator<BeginIteratorType>(r_.begin());
   }
-  Enumerator<Iterator> end() {
-    return Enumerator<Iterator>(r_.end());
+  Enumerator<EndIteratorType> end() {
+    return Enumerator<EndIteratorType>(r_.end());
   }
 };