diff --git a/CMakeLists.txt b/CMakeLists.txt index a25f735..9da53f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 1.1.1) +set(BLT_VERSION 1.1.2) set(BLT_TARGET BLT) diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h index 6fa91b8..746af3c 100644 --- a/include/blt/iterator/common.h +++ b/include/blt/iterator/common.h @@ -25,16 +25,16 @@ namespace blt::iterator { template - struct wrapper_base + struct base_wrapper { - wrapper_base operator++(int) + base_wrapper operator++(int) { auto tmp = *this; ++*this; return tmp; } - wrapper_base operator--(int) + base_wrapper operator--(int) { static_assert(std::is_same_v || std::is_same_v, @@ -51,80 +51,75 @@ namespace blt::iterator return *(*this + n); } - friend wrapper_base operator+(const wrapper_base& a, blt::ptrdiff_t n) + friend base_wrapper operator+(blt::ptrdiff_t n, const base_wrapper& a) { - static_assert(std::is_same_v, - "Iterator must allow random access"); - auto copy = a; - copy += n; - return copy; + return a + n; } - friend wrapper_base operator+(blt::ptrdiff_t n, const wrapper_base& a) - { - static_assert(std::is_same_v, - "Iterator must allow random access"); - auto copy = a; - copy += n; - return copy; - } - - friend wrapper_base operator-(const wrapper_base& a, blt::ptrdiff_t n) - { - static_assert(std::is_same_v, - "Iterator must allow random access"); - auto copy = a; - copy -= n; - return copy; - } - - friend wrapper_base operator-(blt::ptrdiff_t n, const wrapper_base& a) - { - static_assert(std::is_same_v, - "Iterator must allow random access"); - auto copy = a; - copy -= n; - return copy; - } - - friend bool operator<(const wrapper_base& a, const wrapper_base& b) + friend bool operator<(const base_wrapper& a, const base_wrapper& b) { static_assert(std::is_same_v, "Iterator must allow random access"); return b - a > 0; } - friend bool operator>(const wrapper_base& a, const wrapper_base& b) + friend bool operator>(const base_wrapper& a, const base_wrapper& b) { static_assert(std::is_same_v, "Iterator must allow random access"); return b < a; } - friend bool operator>=(const wrapper_base& a, wrapper_base& b) + friend bool operator>=(const base_wrapper& a, base_wrapper& b) { static_assert(std::is_same_v, "Iterator must allow random access"); return !(a < b); // NOLINT } - friend bool operator<=(const wrapper_base& a, const wrapper_base& b) + friend bool operator<=(const base_wrapper& a, const base_wrapper& b) { static_assert(std::is_same_v, "Iterator must allow random access"); return !(a > b); // NOLINT } - friend bool operator==(const wrapper_base& a, const wrapper_base& b) + friend bool operator==(const base_wrapper& a, const base_wrapper& b) { return a.base() == b.base(); } - friend bool operator!=(const wrapper_base& a, const wrapper_base& b) + friend bool operator!=(const base_wrapper& a, const base_wrapper& b) { return !(a.base() == b.base()); // NOLINT } }; + + template + struct passthrough_wrapper : public base_wrapper + { + public: + explicit passthrough_wrapper(Iter iter): iter(std::move(iter)) + {} + + meta::deref_return_t operator*() const + { + return *iter; + } + + auto base() const + { + return iter; + } + + friend blt::ptrdiff_t operator-(const passthrough_wrapper& a, const passthrough_wrapper& b) + { + return a.base() - b.base(); + } + + protected: + Iter iter; + }; } #endif //BLT_ITERATOR_ITER_COMMON diff --git a/include/blt/iterator/zip.h b/include/blt/iterator/zip.h index f5fd24b..4efb86a 100644 --- a/include/blt/iterator/zip.h +++ b/include/blt/iterator/zip.h @@ -29,7 +29,7 @@ namespace blt namespace iterator { template - class zip_wrapper : public wrapper_base> + struct zip_wrapper : public base_wrapper> { public: using iterator_category = meta::lowest_iterator_category_t; @@ -58,16 +58,18 @@ namespace blt return *this; } - zip_wrapper& operator+=(blt::ptrdiff_t n) + friend zip_wrapper operator+(const zip_wrapper& a, blt::ptrdiff_t n) { - std::apply([n](auto& ... i) { ((i += n), ...); }, this->iter); - return *this; + static_assert(std::is_same_v, + "Iterator must allow random access"); + return std::apply([n](auto& ... i) { return zip_wrapper((i + n)...); }, a.iter); } - zip_wrapper& operator-=(blt::ptrdiff_t n) + friend zip_wrapper operator-(const zip_wrapper& a, blt::ptrdiff_t n) { - std::apply([n](auto& ... i) { ((i -= n), ...); }, this->iter); - return *this; + static_assert(std::is_same_v, + "Iterator must allow random access"); + return std::apply([n](auto& ... i) { return zip_wrapper((i - n)...); }, a.iter); } friend blt::ptrdiff_t operator-(const zip_wrapper& a, const zip_wrapper& b) @@ -93,112 +95,78 @@ namespace blt } }; - BLT_META_MAKE_FUNCTION_CHECK(base); - - template - auto get_base(Iter iter) + template + struct skip_wrapper : public passthrough_wrapper> { - if constexpr (has_func_base_v) - { - return std::move(iter).base(); - } else - { - return std::move(iter); - } - } - - template - class take_impl - { - private: - template - auto take_base(blt::size_t n) - { - static_assert(!std::is_same_v, - "Cannot .take() on an input iterator!"); - auto* d = static_cast(this); - auto begin = d->begin(); - auto end = d->end(); - - // take variant for forward and bidirectional iterators - if constexpr (std::is_same_v || - std::is_same_v) - { - // with these guys we have to loop forward to move the iterators. an unfortunate inefficiency - auto new_end = begin; - for (blt::size_t i = 0; i < n; i++) - { - if constexpr (check) - { - if (new_end == end) - break; - } - ++new_end; - } - return Derived{get_base(std::move(begin)), get_base(std::move(new_end))}; - } else if constexpr (std::is_same_v) - { - // random access iterators can have math directly applied to them. - if constexpr (check) - { - return Derived{get_base(begin), - get_base(begin + std::min(static_cast(n), std::distance(begin, end)))}; - } else - { - return Derived{get_base(begin), get_base(begin + n)}; - } - } - } - public: - auto take(blt::size_t n) - { return take_base(n); } + using iterator_category = typename std::iterator_traits::iterator_category; + using value_type = typename std::iterator_traits::value_type; + using difference_type = typename std::iterator_traits::difference_type; + using pointer = typename std::iterator_traits::pointer; + using reference = typename std::iterator_traits::reference; - auto take_or(blt::size_t n) - { return take_base(n); } - }; - - template - class skip_impl - { - private: - template - auto skip_base(blt::size_t n) + explicit skip_wrapper(Iter iter, blt::size_t n): passthrough_wrapper>(std::move(iter)), skip(n) + {} + + skip_wrapper& operator++() { - auto* d = static_cast(this); - auto begin = d->begin(); - auto end = d->end(); - - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) { - if constexpr (check) + if (skip > 0) { - return Derived{begin + std::min(static_cast(n), std::distance(begin, end))}; - } else - { - return Derived{begin + n, end}; + this->base() += skip; + skip = 0; } } else { - for (blt::size_t i = 0; i < n; i++) + while (skip > 0) { - if constexpr (check) - { - if (begin == end) - break; - } - ++begin; + ++this->base(); + --skip; } - return Derived{begin, end}; } + + ++this->base(); + return *this; + } + + skip_wrapper& operator--() + { + if constexpr (std::is_same_v) + { + if (skip > 0) + { + this->base() -= skip; + skip = 0; + } + } else + { + while (skip > 0) + { + --this->base(); + --skip; + } + } + --this->base(); + return *this; + } + + friend skip_wrapper operator+(const skip_wrapper& a, blt::ptrdiff_t n) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return {a.base() + static_cast(a.skip) + n, 0}; + } + + friend skip_wrapper operator-(const skip_wrapper& a, blt::ptrdiff_t n) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return {a.base() - static_cast(a.skip) - n, 0}; } - public: - void skip(blt::size_t n) - { return skip_base(n); } - - void skip_or(blt::size_t n) - { return skip_base(n); } + private: + blt::size_t skip; }; } @@ -221,7 +189,7 @@ namespace blt class zip_iterator_storage_rev; template - class zip_iterator_storage : public iterator::take_impl> + class zip_iterator_storage { public: using iterator_category = meta::lowest_iterator_category_t; @@ -244,10 +212,7 @@ namespace blt auto skip(blt::size_t n) { - if constexpr (std::is_same_v) - { - - } + } auto begin() const @@ -266,7 +231,7 @@ namespace blt }; template - class zip_iterator_storage_rev : public iterator::take_impl> + class zip_iterator_storage_rev { public: using iterator_category = meta::lowest_iterator_category_t; @@ -329,7 +294,7 @@ namespace blt template auto zip(Container& ... container) { - return blt::zip_iterator_storage{iterator_pair{container.begin(), container.end()}...}; + return zip_iterator_storage{iterator_pair{container.begin(), container.end()}...}; } }