瀏覽代碼

refactor: add sentinel difference features (TODO: move back to facade)

Sam Jaffe 2 年之前
父節點
當前提交
52b436acc9
共有 3 個文件被更改,包括 20 次插入6 次删除
  1. 8 5
      include/iterator/detail/traits.h
  2. 5 0
      include/iterator/end_aware_iterator.h
  3. 7 1
      include/iterator/proxy.h

+ 8 - 5
include/iterator/detail/traits.h

@@ -22,10 +22,13 @@ template <typename C>
 struct is_container<C, std::void_t<iter<C>>> : std::true_type {};
 
 template <typename It, typename = void>
-struct has_sentinel_type : std::false_type {};
+struct sentinel_type {
+  using type = void;
+};
 template <typename It>
-struct has_sentinel_type<It, std::void_t<typename It::sentinel_type>>
-    : std::true_type {};
+struct sentinel_type<It, std::void_t<typename It::sentinel_type>> {
+  using type = typename It::sentinel_type;
+};
 }
 
 // Mappings between iterator::category enum and iterator_category tags
@@ -78,10 +81,10 @@ template <typename Iter>
 constexpr bool is_rvalue_iterator_v = !std::is_reference_v<DEREF_TYPE(Iter)>;
 
 template <typename It>
-constexpr bool has_sentinel_type_v = has_sentinel_type<It>{};
+constexpr bool has_sentinel_type_v = !std::is_void_v<typename sentinel_type<It>::type>;
 
 template <typename It, typename S>
-using sentinel_type = std::conditional_t<std::is_same_v<It, S>, sentinel_t, S>;
+constexpr bool is_sentinel_v = std::is_same_v<typename sentinel_type<It>::type, S>;
 
 template <typename It, category Limit = static_cast<category>(~0)>
 constexpr auto category_for_v = category_for<category_t<It>, Limit>::value;

+ 5 - 0
include/iterator/end_aware_iterator.h

@@ -49,6 +49,11 @@ public:
       return super_t::impl() == end_;
     }
   }
+  
+  SFINAE(super_t::category_enum == category::random_access)
+  friend auto operator-(sentinel_type, end_aware_iterator const &self) {
+    return self.end() - self.impl();
+  }
 
 protected:
   It end() const { return end_; }

+ 7 - 1
include/iterator/proxy.h

@@ -94,8 +94,14 @@ public:
   difference_type distance_to(Self const & other) const {
     return other.impl_ - impl_;
   }
+  
+  template <typename S, REQUIRES((detail::is_sentinel_v<It, S>))>
+  friend auto operator-(S sentinel, Self const &self) {
+    return sentinel - self.impl();
+  }
+  
   SFINAE(detail::has_sentinel_type_v<It>) bool at_end() const {
-    return impl() == typename It::sentinel_type();
+    return (typename It::sentinel_type() - impl()) <= 0;
   }
 
 protected: