Fix Enumerate C++17 Support
authorNick Terrell <terrelln@fb.com>
Thu, 4 Aug 2016 00:53:52 +0000 (17:53 -0700)
committerFacebook Github Bot 0 <facebook-github-bot-0-bot@fb.com>
Thu, 4 Aug 2016 01:08:26 +0000 (18:08 -0700)
Summary: `RangeEnumerator`s `begin()` and `end()` could return different values, but `Enumerator`s `operator ==` didn't support comparision with different types.

Reviewed By: yfeldblum

Differential Revision: D3662576

fbshipit-source-id: cfd10fffd220c70191ce0ac2ed78edd35daf5538

folly/Enumerate.h
folly/test/EnumerateTest.cpp

index 5733bfb6fa528e542c3849c5840dea3433a363df..f4fb12bebaec79a23e9b5b21037ce5422c7ff800 100644 (file)
@@ -108,15 +108,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;
 };
index 5466ddcd1c55a9a81de208a35517e7bb7075277f..47ae5cd94df8d36077701029cbffc2bb227857ae 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <array>
 #include <string>
 #include <vector>
 
@@ -129,3 +130,41 @@ TEST(Enumerate, EmptyRange) {
     EXPECT_TRUE(false);
   }
 }
+
+class CStringRange {
+  const char* cstr;
+
+ public:
+  struct Sentinel {};
+
+  explicit CStringRange(const char* cstr) : cstr(cstr) {}
+
+  const char* begin() const {
+    return cstr;
+  }
+  Sentinel end() const {
+    return Sentinel{};
+  }
+};
+
+bool operator==(const char* c, CStringRange::Sentinel) {
+  return *c == 0;
+}
+
+TEST(Enumerate, Cpp17Support) {
+  std::array<char, 5> test = {"test"};
+  // Can't use range based for loop until C++17, so test manually
+  // Equivalent to:
+  // for (const auto it : folly::enumerate(CStringRange{test.data()})) { ... }
+  {
+    auto&& enumerate = folly::enumerate(CStringRange{test.data()});
+    auto begin = enumerate.begin();
+    auto end = enumerate.end();
+    for (; begin != end; ++begin) {
+      const auto it = *begin;
+
+      ASSERT_LT(it.index, test.size());
+      EXPECT_EQ(*it, test[it.index]);
+    }
+  }
+}