diff --git a/CMakeLists.txt b/CMakeLists.txt index 9384be6..6601997 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 2.1.13) +set(BLT_VERSION 2.1.14) set(BLT_TARGET BLT) diff --git a/commit.py b/commit.py old mode 100644 new mode 100755 diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h index ce2805d..d98ddeb 100644 --- a/include/blt/iterator/common.h +++ b/include/blt/iterator/common.h @@ -30,7 +30,7 @@ namespace blt::iterator { - template + template struct base_wrapper { base_wrapper operator++(int) @@ -39,7 +39,7 @@ namespace blt::iterator ++*this; return tmp; } - + base_wrapper operator--(int) { static_assert(meta::is_bidirectional_or_better_category_v, "Iterator must allow random access"); @@ -47,347 +47,373 @@ namespace blt::iterator --*this; return tmp; } - + auto operator[](blt::ptrdiff_t n) const { static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return *(*this + n); } - + friend base_wrapper operator+(blt::ptrdiff_t n, const base_wrapper& a) { return a + n; } - + friend bool operator<(const base_wrapper& a, const base_wrapper& b) { static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return b - a > 0; } - + friend bool operator>(const base_wrapper& a, const base_wrapper& b) { static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return b < a; } - + friend bool operator>=(const base_wrapper& a, base_wrapper& b) { static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return !(a < b); // NOLINT } - + friend bool operator<=(const base_wrapper& a, const base_wrapper& b) { static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return !(a > b); // NOLINT } - + friend bool operator==(const base_wrapper& a, const base_wrapper& b) { return static_cast(a).base() == static_cast(b).base(); } - + friend bool operator!=(const base_wrapper& a, const base_wrapper& b) { return !(static_cast(a).base() == static_cast(b).base()); // NOLINT } }; - - template + + template struct passthrough_wrapper : public base_wrapper { - public: - explicit passthrough_wrapper(Iter iter): iter(std::move(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: - mutable Iter iter; + public: + explicit passthrough_wrapper(Iter iter): iter(std::move(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: + mutable Iter iter; }; - - template + + template struct passthrough_wrapper : public passthrough_wrapper { using passthrough_wrapper::passthrough_wrapper; - + meta::deref_return_t operator*() const { return *this->iter; } }; - - template + + template class deref_only_wrapper : public passthrough_wrapper { - public: - using passthrough_wrapper::passthrough_wrapper; - - deref_only_wrapper& operator++() - { - ++this->iter; - return *this; - } - - deref_only_wrapper& operator--() - { - --this->iter; - return *this; - } - - deref_only_wrapper& operator+(blt::ptrdiff_t n) - { - static_assert(meta::is_random_access_iterator_v, "Iterator must allow random access"); - this->iter = this->iter + n; - return *this; - } - - deref_only_wrapper& operator-(blt::ptrdiff_t n) - { - static_assert(meta::is_random_access_iterator_v, "Iterator must allow random access"); - this->iter = this->iter - n; - return *this; - } + public: + using passthrough_wrapper::passthrough_wrapper; + + deref_only_wrapper& operator++() + { + ++this->iter; + return *this; + } + + deref_only_wrapper& operator--() + { + --this->iter; + return *this; + } + + deref_only_wrapper& operator+(blt::ptrdiff_t n) + { + static_assert(meta::is_random_access_iterator_v, "Iterator must allow random access"); + this->iter = this->iter + n; + return *this; + } + + deref_only_wrapper& operator-(blt::ptrdiff_t n) + { + static_assert(meta::is_random_access_iterator_v, "Iterator must allow random access"); + this->iter = this->iter - n; + return *this; + } }; - - template + + template class map_wrapper : public deref_only_wrapper> { - public: - using iterator_category = typename std::iterator_traits::iterator_category; - using value_type = std::invoke_result_t>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - - map_wrapper(Iter iter, Func func): - deref_only_wrapper>(std::move(iter)), func(std::move(func)) - {} - - reference operator*() const - { - return func(*this->iter); - } - - private: - Func func; + public: + using iterator_category = typename std::iterator_traits::iterator_category; + using value_type = std::invoke_result_t>; + using difference_type = blt::ptrdiff_t; + using pointer = value_type; + using reference = value_type; + + map_wrapper(Iter iter, Func func): + deref_only_wrapper>(std::move(iter)), func(std::move(func)) + { + } + + reference operator*() const + { + return func(*this->iter); + } + + private: + Func func; }; - - template + + template class filter_wrapper : public deref_only_wrapper> { - public: - using iterator_category = typename std::iterator_traits::iterator_category; - using value_type = std::conditional_t< - std::is_reference_v>, - std::optional>>>, - std::optional>>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - - filter_wrapper(Iter iter, Pred func): - deref_only_wrapper>(std::move(iter)), func(std::move(func)) - {} - - reference operator*() const + public: + using iterator_category = typename std::iterator_traits::iterator_category; + using value_type = std::conditional_t< + std::is_reference_v>, + std::optional>>>, + std::optional>>; + using difference_type = blt::ptrdiff_t; + using pointer = value_type; + using reference = value_type; + + filter_wrapper(Iter iter, Pred func): + deref_only_wrapper>(std::move(iter)), func(std::move(func)) + { + } + + reference operator*() const + { + if (!func(*this->iter)) { - if (!func(*this->iter)) - { - return {}; - } - return *this->iter; + return {}; } - - private: - Pred func; + return *this->iter; + } + + private: + Pred func; }; - + namespace impl { - template + template class skip_t { - private: - template - auto skip_base(blt::size_t n) + private: + template + auto skip_base(blt::size_t n) + { + auto* d = static_cast(this); + auto begin = d->begin(); + auto end = d->end(); + + if constexpr (meta::is_random_access_iterator_category_v) { - auto* d = static_cast(this); - auto begin = d->begin(); - auto end = d->end(); - - if constexpr (meta::is_random_access_iterator_category_v) + // random access iterators can have math directly applied to them. + if constexpr (check) { - // random access iterators can have math directly applied to them. - if constexpr (check) - { - return Derived{begin + std::min(static_cast(n), std::distance(begin, end)), end}; - } else - { - return Derived{begin + n, end}; - } - } else + return Derived{begin + std::min(static_cast(n), std::distance(begin, end)), end}; + } + else { - for (blt::size_t i = 0; i < n; i++) - { - if constexpr (check) - { - if (begin == end) - break; - } - ++begin; - } - return Derived{std::move(begin), std::move(end)}; + return Derived{begin + n, end}; } } - - public: - auto skip(blt::size_t n) - { return skip_base(n); } - - auto skip_or(blt::size_t n) - { return skip_base(n); } + else + { + for (blt::size_t i = 0; i < n; i++) + { + if constexpr (check) + { + if (begin == end) + break; + } + ++begin; + } + return Derived{std::move(begin), std::move(end)}; + } + } + + public: + auto skip(blt::size_t n) + { + return skip_base(n); + } + + auto skip_or(blt::size_t n) + { + return skip_base(n); + } }; - - template + + template class take_t { - private: - template - auto take_base(blt::size_t n) + private: + template + auto take_base(blt::size_t n) + { + static_assert(!meta::is_input_iterator_category_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 (meta::is_forward_iterator_category_v || + meta::is_bidirectional_iterator_category_v) { - static_assert(!meta::is_input_iterator_category_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 (meta::is_forward_iterator_category_v || - meta::is_bidirectional_iterator_category_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++) { - // 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{std::move(begin), std::move(new_end)}; - } else if constexpr (meta::is_random_access_iterator_category_v) - { - // random access iterators can have math directly applied to them. if constexpr (check) { - return Derived{begin, begin + std::min(static_cast(n), std::distance(begin, end))}; - } else - { - return Derived{begin, begin + n}; + if (new_end == end) + break; } + ++new_end; + } + return Derived{std::move(begin), std::move(new_end)}; + } + else if constexpr (meta::is_random_access_iterator_category_v) + { + // random access iterators can have math directly applied to them. + if constexpr (check) + { + return Derived{begin, begin + std::min(static_cast(n), std::distance(begin, end))}; + } + else + { + return Derived{begin, begin + n}; } } - - public: - auto take(blt::size_t n) - { return take_base(n); } - - auto take_or(blt::size_t n) - { return take_base(n); } + } + + public: + auto take(blt::size_t n) + { + return take_base(n); + } + + auto take_or(blt::size_t n) + { + return take_base(n); + } }; } - - template + + template class iterator_container : public impl::take_t>, public impl::skip_t> { - public: - using iterator_category = typename std::iterator_traits::iterator_category; - using iterator = IterBase; - - iterator_container(IterBase begin, IterBase end): m_begin(std::move(begin)), m_end(std::move(end)) - {} - - template - iterator_container(Iter&& begin, Iter&& end): m_begin(std::forward(begin)), m_end(std::forward(end)) - {} - - auto rev() const - { - static_assert(meta::is_bidirectional_or_better_category_v, - ".rev() must be used with bidirectional (or better) iterators!"); - return iterator_container>{std::reverse_iterator{end()}, - std::reverse_iterator{begin()}}; - } - - template - auto zip(iterator_pair... iterator_pairs) const - { - return zip_iterator_container(iterator_pair{begin(), end()}, iterator_pairs...); - } - - template - auto zip(Container& ... containers) const - { - return zip_iterator_container(iterator_pair{begin(), end()}, - iterator_pair{containers.begin(), containers.end()}...); - } - - template - auto zip(const Container& ... containers) const - { - return zip_iterator_container(iterator_pair{begin(), end()}, - iterator_pair{containers.begin(), containers.end()}...); - } - - auto enumerate() const - { - return enumerate_iterator_container{begin(), end(), static_cast(std::distance(begin(), end()))}; - } - - template - auto map(Func func) const - { - return iterator_container>{ - blt::iterator::map_wrapper{m_begin, func}, - blt::iterator::map_wrapper{m_end, func}}; - } - - template - auto filter(Pred pred) const - { - return iterator_container>{ - blt::iterator::filter_wrapper{m_begin, pred}, - blt::iterator::filter_wrapper{m_end, pred}}; - } - - auto begin() const - { - return m_begin; - } - - auto end() const - { - return m_end; - } - - protected: - IterBase m_begin; - IterBase m_end; + public: + using iterator_category = typename std::iterator_traits::iterator_category; + using iterator = IterBase; + + iterator_container(IterBase begin, IterBase end): m_begin(std::move(begin)), m_end(std::move(end)) + { + } + + template + iterator_container(Iter&& begin, Iter&& end): m_begin(std::forward(begin)), m_end(std::forward(end)) + { + } + + auto rev() const + { + static_assert(meta::is_bidirectional_or_better_category_v, + ".rev() must be used with bidirectional (or better) iterators!"); + return iterator_container>{ + std::reverse_iterator{end()}, + std::reverse_iterator{begin()} + }; + } + + template + auto zip(iterator_pair... iterator_pairs) const + { + return zip_iterator_container(iterator_pair{begin(), end()}, iterator_pairs...); + } + + template + auto zip(Container&... containers) const + { + return zip_iterator_container(iterator_pair{begin(), end()}, + iterator_pair{containers.begin(), containers.end()}...); + } + + template + auto zip(const Container&... containers) const + { + return zip_iterator_container(iterator_pair{begin(), end()}, + iterator_pair{containers.begin(), containers.end()}...); + } + + template + auto zip(Iter begin, Iter end) + { + return zip(iterator_pair{begin, end}); + } + + auto enumerate() const + { + return enumerate_iterator_container{begin(), end(), static_cast(std::distance(begin(), end()))}; + } + + template + auto map(Func func) const + { + return iterator_container>{ + blt::iterator::map_wrapper{m_begin, func}, + blt::iterator::map_wrapper{m_end, func} + }; + } + + template + auto filter(Pred pred) const + { + return iterator_container>{ + blt::iterator::filter_wrapper{m_begin, pred}, + blt::iterator::filter_wrapper{m_end, pred} + }; + } + + auto begin() const + { + return m_begin; + } + + auto end() const + { + return m_end; + } + + protected: + IterBase m_begin; + IterBase m_end; }; - } #endif //BLT_ITERATOR_ITER_COMMON