Add support in enumerate() for iterators with exotic pointers
authorGiuseppe Ottaviano <ott@fb.com>
Wed, 12 Oct 2016 04:12:59 +0000 (21:12 -0700)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Wed, 12 Oct 2016 04:23:31 +0000 (21:23 -0700)
Summary: I thought we wouldn't need this but it turns out Thrift Frozen2 iterators return proxies (it's proxies all the way down). Thanks to ericniebler for trick.

Reviewed By: yfeldblum

Differential Revision: D4005700

fbshipit-source-id: 1911996afa075c1d819a3aaea2ee924bc2ae2f20

folly/Enumerate.h

index f4fb12bebaec79a23e9b5b21037ce5422c7ff800..28681487f83b7e28187db24b9f808cd7cf266188 100644 (file)
@@ -60,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:
@@ -80,7 +92,7 @@ class Enumerator {
       return *it_;
     }
     pointer operator->() {
-      return std::addressof(**this);
+      return getPointer(it_, 0);
     }
 
     // Const Proxy: Force const references.
@@ -88,7 +100,7 @@ class Enumerator {
       return *it_;
     }
     typename MakeConst<pointer>::type operator->() const {
-      return std::addressof(**this);
+      return getPointer(it_, 0);
     }
 
    private: