Przeglądaj źródła

feat: add sentinal_iterator

refactor: change void_t => std::void_t
Sam Jaffe 2 lat temu
rodzic
commit
ef9f846c79

+ 4 - 6
include/iterator/detail/traits.h

@@ -1,18 +1,16 @@
 #pragma once
 
 #define _val(type) std::declval<type>()
-#define exists(expr) void_t<decltype(expr)>
+#define exists(expr) std::void_t<decltype(expr)>
 
 #include <iterator/iterator_fwd.hpp>
 
 namespace iterator::detail {
-template <typename> using void_t = void;
-
 template <typename T, typename = void> struct reference_helper {
   using type = decltype(*std::declval<T>());
 };
 template <typename T>
-struct reference_helper<T, void_t<typename T::reference>> {
+struct reference_helper<T, std::void_t<typename T::reference>> {
   using type = typename T::reference;
 };
 
@@ -21,7 +19,7 @@ template <typename T, typename = void> struct value_type_helper {
   using type = std::remove_cv_t<std::remove_reference_t<reference>>;
 };
 template <typename T>
-struct value_type_helper<T, void_t<typename T::value_type>> {
+struct value_type_helper<T, std::void_t<typename T::value_type>> {
   using type = typename T::value_type;
 };
 
@@ -30,7 +28,7 @@ template <typename T> using reference = typename reference_helper<T>::type;
 
 template <typename C, typename = void> struct is_container : std::false_type {};
 template <typename C>
-struct is_container<C, void_t<iter<C>>> : std::true_type {};
+struct is_container<C, std::void_t<iter<C>>> : std::true_type {};
 
 template <typename C> constexpr bool is_container_v = is_container<C>{};
 

+ 10 - 4
include/iterator/end_aware_iterator.hpp

@@ -21,8 +21,8 @@ namespace iterator {
 template <typename It>
 class end_aware_iterator : public facade<end_aware_iterator<It>> {
 public:
-  struct sentinel_type {};
-  static constexpr sentinel_type sentinel;
+  struct sentinal_type {};
+  static constexpr sentinal_type sentinal;
 
 public:
   end_aware_iterator() = default;
@@ -35,8 +35,11 @@ public:
                   "Cannot access iterator of a temporary");
   }
 
-  template <typename I>
-  end_aware_iterator(end_aware_iterator<I> const & other)
+  template <typename Ot>
+  end_aware_iterator(end_aware_iterator<Ot> const & other)
+      : curr_(other.curr_), end_(other.end_) {}
+
+  end_aware_iterator(end_aware_iterator<It> other, end_aware_iterator<It>)
       : curr_(other.curr_), end_(other.end_) {}
 
   decltype(auto) dereference() const { return *curr_; }
@@ -54,6 +57,9 @@ private:
 
 template <typename C> end_aware_iterator(C &&) -> end_aware_iterator<iter<C>>;
 template <typename It> end_aware_iterator(It, It) -> end_aware_iterator<It>;
+template <typename It>
+end_aware_iterator(end_aware_iterator<It>, end_aware_iterator<It>)
+    -> end_aware_iterator<It>;
 }
 
 MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::end_aware_iterator);

+ 5 - 5
include/iterator/facade.h

@@ -26,7 +26,7 @@ struct is_advanceable_iterator<T, exists(_val(T).advance({}))>
 template <typename, typename = void>
 struct is_single_pass_iterator : std::false_type {};
 template <typename T>
-struct is_single_pass_iterator<T, void_t<typename T::single_pass_iterator>>
+struct is_single_pass_iterator<T, std::void_t<typename T::single_pass_iterator>>
     : std::true_type {};
 
 template <typename, typename = void> struct has_increment : std::false_type {};
@@ -51,7 +51,7 @@ template <typename, typename = void> struct sentinal_type {
 };
 
 template <typename T>
-struct sentinal_type<T, void_t<typename T::sentinal_type>> {
+struct sentinal_type<T, std::void_t<typename T::sentinal_type>> {
   using type = typename T::sentinal_type;
 };
 
@@ -92,7 +92,7 @@ using difference_type_arg_t =
     std::enable_if_t<std::is_convertible_v<D, detail::distance_to_t<T>>>;
 
 template <typename D, typename T>
-using sentinel_type_arg_t =
+using sentinal_type_arg_t =
     std::enable_if_t<std::is_same_v<D, detail::sentinal_type_t<T>>>;
 
 template <typename self_type> class facade {
@@ -195,12 +195,12 @@ public:
     }
   }
 
-  template <typename S, typename = sentinel_type_arg_t<S, self_type>>
+  template <typename S, typename = sentinal_type_arg_t<S, self_type>>
   friend auto operator==(self_type self, S) {
     return self.at_end();
   }
 
-  template <typename S, typename = sentinel_type_arg_t<S, self_type>>
+  template <typename S, typename = sentinal_type_arg_t<S, self_type>>
   friend auto operator!=(self_type self, S) {
     return !self.at_end();
   }

+ 5 - 0
include/iterator/filter_iterator.hpp

@@ -18,6 +18,9 @@ namespace iterator {
 template <typename Iter, bool Cache>
 class filter_iterator : public facade<filter_iterator<Iter, Cache>> {
 public:
+  struct sentinal_type {};
+  static constexpr sentinal_type sentinal;
+
   using reference = typename std::iterator_traits<Iter>::reference;
   using cache_t = std::conditional_t<Cache, detail::value_proxy<reference>,
                                      detail::ignore_proxy>;
@@ -44,6 +47,8 @@ public:
       base_.increment();
     } while (should_advance());
   }
+
+  bool at_end() const { return base_.at_end(); }
   bool equal_to(filter_iterator const & other) const {
     return base_ == other.base_;
   }

+ 17 - 16
include/iterator/join_iterator.hpp

@@ -16,8 +16,7 @@
 #include <iterator/iterator_fwd.hpp>
 
 namespace iterator::joining {
-template <typename Iter, typename = void>
-class iterator {
+template <typename Iter, typename = void> class iterator {
 protected:
   using inner_t = decltype(*std::declval<Iter>());
 
@@ -33,7 +32,7 @@ protected:
       : iterator(end_aware_iterator(std::forward<C>(container))) {}
 
   iterator(end_aware_iterator<Iter> join) : iterator(join, {}, true) {}
-  
+
   iterator(end_aware_iterator<Iter> join,
            end_aware_iterator<iter<inner_t>> elem, bool update = false)
       : joiner_(join), element_(elem) {
@@ -64,16 +63,14 @@ protected:
     update_iterator();
   }
 
-  iterator(end_aware_iterator<Iter> join) : joiner_(join) {
-    update_iterator();
-  }
-  
+  iterator(end_aware_iterator<Iter> join) : joiner_(join) { update_iterator(); }
+
   void update_iterator() {
     while (!joiner_.at_end() && sync().at_end()) {
       ++joiner_;
     }
   }
-  
+
 private:
   end_aware_iterator<iter<inner_t>> const & sync() {
     if (joiner_.at_end()) { return element_ = {}; }
@@ -91,18 +88,21 @@ protected:
 
 namespace iterator {
 template <typename Iter>
-class joining_iterator : public facade<joining_iterator<Iter>>, public joining::iterator<Iter> {
+class joining_iterator : public facade<joining_iterator<Iter>>,
+                         public joining::iterator<Iter> {
 public:
   using super_t = joining::iterator<Iter>;
-  
+  struct sentinal_type {};
+  static constexpr sentinal_type sentinal;
+
 public:
   using super_t::super_t;
-  
+
   template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
   joining_iterator(C && container) : super_t(std::forward<C>(container)) {}
 
   joining_iterator(end_aware_iterator<Iter> join) : super_t(join) {}
-  
+
   void increment() {
     if ((++super_t::element_).at_end()) {
       ++super_t::joiner_;
@@ -112,13 +112,14 @@ public:
 
   decltype(auto) dereference() const { return *super_t::element_; }
 
+  bool at_end() const { return join_iterator().at_end(); }
   bool equal_to(joining_iterator const & other) const {
     return join_iterator() == other.join_iterator() &&
-        element_iterator() == other.element_iterator();
+           element_iterator() == other.element_iterator();
   }
-  
-  auto const &join_iterator() const { return super_t::joiner_; }
-  auto const &element_iterator() const { return super_t::element_; }
+
+  auto const & join_iterator() const { return super_t::joiner_; }
+  auto const & element_iterator() const { return super_t::element_; }
 };
 
 template <typename C> joining_iterator(C &&) -> joining_iterator<iter<C>>;

+ 48 - 0
include/iterator/sentinal_iterator.h

@@ -0,0 +1,48 @@
+//
+//  sentinal_iterator.h
+//  iterator
+//
+//  Created by Sam Jaffe on 3/30/23.
+//  Copyright © 2023 Sam Jaffe. All rights reserved.
+//
+
+#pragma once
+
+#include <iterator/detail/traits.h>
+#include <iterator/facade.h>
+#include <iterator/iterator_fwd.hpp>
+
+namespace iterator {
+template <typename It>
+class sentinal_iterator : public facade<sentinal_iterator<It>> {
+public:
+  using sentinal_type = typename It::sentinal_type;
+  static constexpr sentinal_type sentinal{};
+
+public:
+  sentinal_iterator() = default;
+  sentinal_iterator(It it) : curr_(it) {}
+
+  template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
+  sentinal_iterator(C && container) : curr_(std::begin(container)) {
+    static_assert(std::is_reference_v<C>,
+                  "Cannot access iterator of a temporary");
+  }
+
+  decltype(auto) dereference() const { return *curr_; }
+  void increment() { ++curr_; }
+  bool at_end() const { return curr_.at_end() || curr_ == It(); }
+  bool equal_to(sentinal_iterator const & other) const {
+    // TODO: Fix this clause
+    return (at_end() && other.at_end()) || curr_ == other.curr_;
+  }
+
+private:
+  It curr_;
+};
+
+template <typename C> sentinal_iterator(C &&) -> sentinal_iterator<iter<C>>;
+template <typename It> sentinal_iterator(It) -> sentinal_iterator<It>;
+}
+
+MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::sentinal_iterator);

+ 2 - 0
iterator.xcodeproj/project.pbxproj

@@ -62,6 +62,7 @@
 
 /* Begin PBXFileReference section */
 		CD3C6DDB26238F8F00548B64 /* xcode_gtest_helper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xcode_gtest_helper.h; sourceTree = "<group>"; };
+		CD6EBE2229D5C93A00F387C1 /* sentinal_iterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sentinal_iterator.h; sourceTree = "<group>"; };
 		CDA2B60928581255004D5353 /* libiterator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libiterator.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDA2B6122858128C004D5353 /* iterator_fwd.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = iterator_fwd.hpp; sourceTree = "<group>"; };
 		CDA2B6132858128C004D5353 /* facade.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = facade.h; sourceTree = "<group>"; };
@@ -171,6 +172,7 @@
 				CDA2B6162858128C004D5353 /* recursive_iterator.hpp */,
 				CDA2B6172858128C004D5353 /* detail */,
 				CDA2B61B2858128C004D5353 /* end_aware_iterator.hpp */,
+				CD6EBE2229D5C93A00F387C1 /* sentinal_iterator.h */,
 				CDA2B61C2858128C004D5353 /* proxy.h */,
 				CDA2B61D2858128C004D5353 /* zip_iterator.hpp */,
 				CDA2B61E2858128C004D5353 /* filter_iterator.hpp */,