/*
- * 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.
#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.
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:
return *it_;
}
pointer operator->() {
- return std::addressof(**this);
+ return getPointer(it_, 0);
}
// Const Proxy: Force const references.
return *it_;
}
typename MakeConst<pointer>::type operator->() const {
- return std::addressof(**this);
+ return getPointer(it_, 0);
}
private:
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;
};
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());
}
};