|
|
@@ -9,76 +9,52 @@
|
|
|
|
|
|
#include "iterator_fwd.hpp"
|
|
|
|
|
|
-#include <iterator>
|
|
|
+#include "facade.h"
|
|
|
|
|
|
namespace iterator {
|
|
|
/**
|
|
|
* @class end_aware_iterator
|
|
|
* @brief An iterator that keeps track of the relative end of the range.
|
|
|
*
|
|
|
- * @tparam Iterator The underlying iterator type
|
|
|
+ * @tparam It The underlying iterator type
|
|
|
*/
|
|
|
- template <typename Iterator> class end_aware_iterator {
|
|
|
+ template <typename It>
|
|
|
+ class end_aware_iterator : public facade<end_aware_iterator<It>> {
|
|
|
public:
|
|
|
- using iter_type = Iterator;
|
|
|
- using value_type = typename std::iterator_traits<iter_type>::value_type;
|
|
|
- using reference = typename std::iterator_traits<iter_type>::reference;
|
|
|
- using pointer = typename std::iterator_traits<iter_type>::pointer;
|
|
|
- using difference_type =
|
|
|
- typename std::iterator_traits<iter_type>::difference_type;
|
|
|
- using iterator_category = std::forward_iterator_tag;
|
|
|
+ using value_type = typename It::value_type;
|
|
|
+ struct sentinel_type {};
|
|
|
+ static constexpr sentinel_type sentinel;
|
|
|
|
|
|
public:
|
|
|
end_aware_iterator() = default;
|
|
|
- end_aware_iterator(iter_type it, iter_type end) : curr_(it), end_(end) {}
|
|
|
- end_aware_iterator(iter_type end) : curr_(end), end_(end) {}
|
|
|
+ end_aware_iterator(It it, It end) : curr_(it), end_(end) {}
|
|
|
+ end_aware_iterator(It end) : curr_(end), end_(end) {}
|
|
|
|
|
|
template <typename I>
|
|
|
end_aware_iterator(end_aware_iterator<I> const & other)
|
|
|
: curr_(other.current()), end_(other.end()) {}
|
|
|
|
|
|
- end_aware_iterator & operator++() {
|
|
|
- if (!done()) { ++curr_; }
|
|
|
- return *this;
|
|
|
+ decltype(auto) dereference() const { return *curr_; }
|
|
|
+ void increment() { ++curr_; }
|
|
|
+ bool at_end() const { return curr_ == end_; }
|
|
|
+ bool equal_to(end_aware_iterator const & other) const {
|
|
|
+ // TODO: Fix this clause
|
|
|
+ return (at_end() && other.at_end()) || curr_ == other.curr_;
|
|
|
}
|
|
|
|
|
|
- end_aware_iterator operator++(int) {
|
|
|
- end_aware_iterator tmp{*this};
|
|
|
- operator++();
|
|
|
- return tmp;
|
|
|
- }
|
|
|
-
|
|
|
- reference operator*() const { return *curr_; }
|
|
|
- pointer operator->() const { return std::addressof(*curr_); }
|
|
|
-
|
|
|
- bool done() const { return curr_ == end_; }
|
|
|
- /**
|
|
|
- * When comparing iterators that do not point to the same collection/range,
|
|
|
- * the result is not specified by the standard. Therefore, as a matter of
|
|
|
- * convenience, even if the underlying data is different, all end-aware
|
|
|
- * iterators in the done() state are considered equal.
|
|
|
- *
|
|
|
- * @see done
|
|
|
- * @return true if both iterators are done, or if the underlying iterators
|
|
|
- * are logically equal
|
|
|
- */
|
|
|
- bool operator==(end_aware_iterator const & other) const {
|
|
|
- return (done() && other.done()) ||
|
|
|
- (curr_ == other.curr_ && end_ == other.end_);
|
|
|
- }
|
|
|
-
|
|
|
- bool operator!=(end_aware_iterator const & other) {
|
|
|
- return !(operator==(other));
|
|
|
- }
|
|
|
-
|
|
|
- iter_type current() const { return curr_; }
|
|
|
- iter_type end() const { return end_; }
|
|
|
+ It current() const { return curr_; }
|
|
|
+ It end() const { return end_; }
|
|
|
|
|
|
private:
|
|
|
- iter_type curr_, end_;
|
|
|
+ It curr_, end_;
|
|
|
};
|
|
|
+
|
|
|
+ template <typename It> end_aware_iterator(It) -> end_aware_iterator<It>;
|
|
|
+ template <typename It> end_aware_iterator(It, It) -> end_aware_iterator<It>;
|
|
|
}
|
|
|
|
|
|
+MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::end_aware_iterator);
|
|
|
+
|
|
|
template <typename Iter>
|
|
|
iterator::end_aware_iterator<Iter> make_end_aware_iterator(Iter a, Iter b) {
|
|
|
return iterator::end_aware_iterator<Iter>(a, b);
|