diff --git a/CMakeLists.txt b/CMakeLists.txt index 29decc6..88a0d95 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.7) +set(BLT_VERSION 1.1.8) set(BLT_TARGET BLT) diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h index 50f3b55..37d8c8f 100644 --- a/include/blt/iterator/common.h +++ b/include/blt/iterator/common.h @@ -21,7 +21,10 @@ #include #include +#include +#include #include +#include namespace blt::iterator { @@ -37,10 +40,7 @@ namespace blt::iterator base_wrapper operator--(int) { - static_assert(std::is_same_v || - std::is_same_v, - "Iterator must allow random access"); + static_assert(meta::is_bidirectional_or_better_category_v, "Iterator must allow random access"); auto tmp = *this; --*this; return tmp; @@ -48,8 +48,7 @@ namespace blt::iterator auto operator[](blt::ptrdiff_t n) const { - static_assert(std::is_same_v, - "Iterator must allow random access"); + static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return *(*this + n); } @@ -60,29 +59,25 @@ namespace blt::iterator friend bool operator<(const base_wrapper& a, const base_wrapper& b) { - static_assert(std::is_same_v, - "Iterator must allow random access"); + 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(std::is_same_v, - "Iterator must allow random access"); + 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(std::is_same_v, - "Iterator must allow random access"); + 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(std::is_same_v, - "Iterator must allow random access"); + static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return !(a > b); // NOLINT } @@ -127,6 +122,28 @@ namespace blt::iterator { return *this->iter; } + +// zip_wrapper& operator++() +// { +// return *this; +// } +// +// zip_wrapper& operator--() +// { +// return *this; +// } +// +// friend zip_wrapper operator+(const zip_wrapper& a, blt::ptrdiff_t n) +// { +// static_assert(std::is_same_v, +// "Iterator must allow random access"); +// } +// +// friend zip_wrapper operator-(const zip_wrapper& a, blt::ptrdiff_t n) +// { +// static_assert(std::is_same_v, +// "Iterator must allow random access"); +// } }; namespace impl @@ -142,8 +159,17 @@ namespace blt::iterator auto begin = d->begin(); auto end = d->end(); - if constexpr (std::is_same_v || - std::is_same_v) + 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 + std::min(static_cast(n), std::distance(begin, end)), end}; + } else + { + return Derived{begin + n, end}; + } + } else { for (blt::size_t i = 0; i < n; i++) { @@ -155,16 +181,6 @@ namespace blt::iterator ++begin; } return Derived{std::move(begin), std::move(end)}; - } else if constexpr (std::is_same_v) - { - // 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}; - } } } @@ -183,15 +199,15 @@ namespace blt::iterator template auto take_base(blt::size_t n) { - static_assert(!std::is_same_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 (std::is_same_v || - std::is_same_v) + 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; @@ -205,7 +221,7 @@ namespace blt::iterator ++new_end; } return Derived{std::move(begin), std::move(new_end)}; - } else if constexpr (std::is_same_v) + } else if constexpr (meta::is_random_access_iterator_category_v) { // random access iterators can have math directly applied to them. if constexpr (check) @@ -232,7 +248,7 @@ namespace blt::iterator public impl::skip_t> { public: - using iterator_category = typename IterBase::iterator_category; + 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)) @@ -242,15 +258,39 @@ namespace blt::iterator iterator_container(Iter&& begin, Iter&& end): m_begin(std::forward(begin)), m_end(std::forward(end)) {} - auto rev() + auto rev() const { - static_assert((std::is_same_v || - std::is_same_v), + 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()))}; + } + auto begin() const { return m_begin; diff --git a/include/blt/iterator/enumerate.h b/include/blt/iterator/enumerate.h index 3747a70..b793f7b 100644 --- a/include/blt/iterator/enumerate.h +++ b/include/blt/iterator/enumerate.h @@ -20,7 +20,6 @@ #define BLT_ITERATOR_ENUMERATE_H #include -#include #include namespace blt @@ -43,17 +42,110 @@ namespace blt class enumerate_wrapper : public passthrough_wrapper> { public: - using passthrough_wrapper>::passthrough_wrapper; + enumerate_wrapper(blt::size_t index, Iter iter): passthrough_wrapper>(std::move(iter)), index(index) + {} + + using iterator_category = typename std::iterator_traits::iterator_category; + using value_type = enumerate_item>; + using difference_type = blt::ptrdiff_t; + using pointer = value_type; + using reference = value_type; enumerate_item> operator*() const { - return *this->iter; + return {index, *this->iter}; } + + enumerate_wrapper& operator++() + { + ++index; + ++this->iter; + return *this; + } + + enumerate_wrapper& operator--() + { + --index; + --this->iter; + return *this; + } + + friend enumerate_wrapper operator+(const enumerate_wrapper& a, blt::ptrdiff_t n) + { + static_assert(meta::is_random_access_iterator_v, "Iterator must allow random access"); + auto copy = a; + copy.index += n; + copy.iter = copy.iter + n; + return copy; + } + + friend enumerate_wrapper operator-(const enumerate_wrapper& a, blt::ptrdiff_t n) + { + static_assert(meta::is_random_access_iterator_v, "Iterator must allow random access"); + auto copy = a; + copy.index -= n; + copy.iter = copy.iter - n; + return copy; + } + private: blt::size_t index; }; } + template + class enumerate_iterator_container : public iterator::iterator_container> + { + public: + using iterator::iterator_container>::iterator_container; + + enumerate_iterator_container(Iter begin, Iter end, blt::size_t size): + iterator::iterator_container>( + iterator::enumerate_wrapper{0, std::move(begin)}, iterator::enumerate_wrapper{size, std::move(end)}) + {} + }; + + template + enumerate_iterator_container(Iter, Iter, blt::size_t) -> enumerate_iterator_container; + + namespace iterator::impl + { + template + class enumerate_t + { + public: + auto enumerate() + { + auto* d = static_cast(this); + return enumerate_iterator_container{d->begin(), d->end(), static_cast(std::distance(d->begin(), d->end()))}; + } + }; + } + + template + static inline auto enumerate(T& container) + { + return enumerate_iterator_container{container.begin(), container.end(), container.size()}; + } + + template + static inline auto enumerate(const T& container) + { + return enumerate_iterator_container{container.begin(), container.end(), container.size()}; + } + + template + static inline auto enumerate(const T(& container)[size]) + { + return enumerate_iterator_container{&container[0], &container[size], size}; + } + + template + static inline auto enumerate(T(& container)[size]) + { + return enumerate_iterator_container{&container[0], &container[size], size}; + } + } #endif //BLT_ITERATOR_ENUMERATE_H diff --git a/include/blt/iterator/fwddecl.h b/include/blt/iterator/fwddecl.h new file mode 100644 index 0000000..36378fa --- /dev/null +++ b/include/blt/iterator/fwddecl.h @@ -0,0 +1,61 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_ITERATOR_FWDDECL_H +#define BLT_ITERATOR_FWDDECL_H + +namespace blt +{ + template + class zip_iterator_container; + + template + class enumerate_iterator_container; + + namespace iterator + { + template + struct iterator_pair; + + template + struct enumerate_item; + + template + class enumerate_wrapper; + + template + struct zip_wrapper; + + namespace impl + { + template + class skip_t; + + template + class take_t; + + template + class zip_t; + + template + class enumerate_t; + } + } +} + +#endif //BLT_ITERATOR_FWDDECL_H diff --git a/include/blt/iterator/iter_common.h b/include/blt/iterator/iter_common.h deleted file mode 100644 index 89f020e..0000000 --- a/include/blt/iterator/iter_common.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -/* - * Copyright (C) 2024 Brett Terpstra - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef BLT_ITERATOR_ITER_COMMON -#define BLT_ITERATOR_ITER_COMMON - -#include -#include - -namespace blt -{ - -} - -#endif //BLT_ITERATOR_ITER_COMMON diff --git a/include/blt/iterator/iterator.h b/include/blt/iterator/iterator.h index 96400eb..4048c52 100644 --- a/include/blt/iterator/iterator.h +++ b/include/blt/iterator/iterator.h @@ -19,12 +19,9 @@ #ifndef BLT_ITERATOR_H #define BLT_ITERATOR_H -#include -#include #include #include -#include -#include +#include #include #include #include @@ -32,723 +29,30 @@ namespace blt { - // forward declare useful types - template> - class enumerator; - - template> - class enumerator_rev; - - template> - class pair_iterator; - - template> - class pair_iterator_rev; - - template - class zip_iterator; - - template - class zip_iterator_rev; - - namespace iterator + template + static inline auto iterate(T& container) { - template> - class enumerate_wrapper; - - template> - class pair_wrapper; - - /** - * struct which is returned by the enumerator. - * @tparam T type to store. - */ - template - struct enumerate_item - { - blt::size_t index; - T value; - }; - - /** - * base class for iterators which operate on pairs of values. Handles comparison. - * @tparam Iter1 first iterator type. this will be used for comparison. - * @tparam Iter2 second iterator type. this value is not modified by this class. - */ - template - class dual_iterator_base - { - public: - explicit dual_iterator_base(Iter1 iter1, Iter2 iter2): m_iter1(std::move(iter1)), m_iter2(std::move(iter2)) - {} - - friend bool operator==(const dual_iterator_base& a, const dual_iterator_base& b) - { - return a.m_iter1 == b.m_iter1; - } - - friend bool operator!=(const dual_iterator_base& a, const dual_iterator_base& b) - { - return a.m_iter1 != b.m_iter1; - } - - auto iter1() const - { - return m_iter1; - } - - auto iter2() const - { - return m_iter2; - } - - protected: - Iter1 m_iter1; - Iter2 m_iter2; - }; - - /** - * Base class for all enumerator iterators. Handles the deference (*) operator. - * @tparam Iter iterator type - */ - template - class enumerate_iterator_base : public dual_iterator_base - { - public: - explicit enumerate_iterator_base(Iter iter, blt::size_t place = 0): - dual_iterator_base(std::move(iter), place) - {} - - enumerate_item> operator*() const - { - return {this->m_iter2, *this->m_iter1}; - } - }; - - template - class pair_iterator_base : public dual_iterator_base - { - public: - using dual_iterator_base::dual_iterator_base; - - std::pair, blt::meta::deref_return_t> operator*() const - { - return {*this->m_iter1, *this->m_iter2}; - } - }; - - /** - * Forward iterator base class. Contains the ++ operator. - * @tparam Base iterator base type. - */ - template - class forward_iterator_base : public Base - { - public: - using Base::Base; - - forward_iterator_base& operator++() - { - ++this->m_iter1; - ++this->m_iter2; - return *this; - } - - forward_iterator_base operator++(int) - { - auto tmp = *this; - ++*this; - return tmp; - } - }; - - /** - * Bidirectional iterator base class. Contains the -- operator. - * @tparam Base iterator base type. - */ - template - class bidirectional_iterator_base : public Base - { - public: - using Base::Base; - - bidirectional_iterator_base& operator--() - { - --this->m_iter1; - --this->m_iter2; - return *this; - } - - bidirectional_iterator_base operator--(int) - { - auto tmp = *this; - --*this; - return tmp; - } - }; - - template - using enumerate_forward_iterator = forward_iterator_base>; - - template - using enumerate_bidirectional_iterator = bidirectional_iterator_base>; - - template - using pair_forward_iterator = forward_iterator_base>; - - template - using pair_bidirectional_iterator = bidirectional_iterator_base>; - - /** - * Enumerator wrapper class specialization for forward iterators. - * @tparam Iter iterator type - */ - template - class enumerate_wrapper, std::void_t>> - : public enumerate_forward_iterator - { - public: - using iterator_category = std::forward_iterator_tag; - using value_type = enumerate_item>; - using difference_type = typename std::iterator_traits::difference_type; - using pointer = value_type; - using reference = value_type; - - using enumerate_forward_iterator::enumerate_forward_iterator; - }; - - /** - * Pair wrapper class specialization for forward iterators. - * @tparam Iter iterator type - */ - template - class pair_wrapper>, - std::void_t>> : public pair_forward_iterator - { - public: - using iterator_category = std::forward_iterator_tag; - using value_type = std::pair, blt::meta::deref_return_t>; - using difference_type = std::common_type_t::difference_type, typename std::iterator_traits::difference_type>; - using pointer = value_type; - using reference = value_type; - - using pair_forward_iterator::pair_forward_iterator; - }; - - /** - * Enumerator wrapper class for bidirectional iterators or random access iterators. - * @tparam Iter iterator type. - */ - template - class enumerate_wrapper, std::void_t>> - : public enumerate_bidirectional_iterator - { - public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = enumerate_item>; - using difference_type = typename std::iterator_traits::difference_type; - using pointer = value_type; - using reference = value_type; - - using enumerate_bidirectional_iterator::enumerate_bidirectional_iterator; - }; - - /** - * Pair wrapper class for bidirectional iterators or random access iterators. - * @tparam Iter iterator type. - */ - template - class pair_wrapper>, - std::void_t>> : public pair_bidirectional_iterator - { - public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::pair, blt::meta::deref_return_t>; - using difference_type = std::common_type_t::difference_type, typename std::iterator_traits::difference_type>; - using pointer = value_type; - using reference = value_type; - - using pair_bidirectional_iterator::pair_bidirectional_iterator; - }; - - /** - * Base class for storing begin/end iterators. - * @tparam IterWrapper wrapper used to iterate - * @tparam CompleteClass completed class returned from skip/take methods - */ - template - class iterator_storage_base - { - public: - explicit iterator_storage_base(IterWrapper begin, IterWrapper end): begin_(std::move(begin)), end_(std::move(end)) - {} - - auto begin() - { - return begin_; - } - - auto end() - { - return end_; - } - - /** - * Creates an enumerator that skips the first n elements. - * @param amount amount of values to skip. - */ - auto skip(blt::size_t amount) - { - auto begin = this->begin_; - for (blt::size_t i = 0; i < amount; i++) - ++begin; - return CompleteClass{begin.iter1(), - this->end_.iter1(), - begin.iter2(), - this->end_.iter2()}; - } - - /** - * Creates an enumerator that yields the first n elements, or UB if the underlying iterator ends sooner. - * @param amount amount to take. - */ - auto take(blt::size_t amount) - { - auto end = this->begin(); - for (blt::size_t i = 0; i < amount; i++) - ++end; - return CompleteClass{this->begin_.iter1(), - end.iter1(), - this->begin_.iter2(), - end.iter2()}; - } - - protected: - IterWrapper begin_; - IterWrapper end_; - }; - - /** - * Reversible (bidirectional) base class storing the begin / end iterators. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate. - * @tparam CompleteClass completed class returned from skip/take methods - * @tparam CompleteClassRev reverse version of CompleteClass, returned from rev - */ - template - class iterator_storage_reversible : public iterator_storage_base - { - public: - explicit iterator_storage_reversible(IterWrapper begin, IterWrapper end): - iterator_storage_base{std::move(begin), std::move(end)} - {} - - /** - * Reverses the enumerator’s direction. - */ - auto rev() const - { - return CompleteClassRev{this->end_.iter1(), - this->begin_.iter1(), - this->end_.iter2(), - this->begin_.iter2()}; - } - }; - - /** - * Random access base class storage for begin/end iterators. - * Has updated skip and take methods which make use of the random access nature of the iterator. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate. - * @tparam CompleteClass completed class returned from skip/take methods - * @tparam CompleteClassRev reverse version of CompleteClass, returned from rev - */ - template - class iterator_storage_random_access : public iterator_storage_reversible - { - public: - using iterator_storage_reversible::iterator_storage_reversible; - - auto skip(blt::size_t amount) - { - return CompleteClass{this->begin_.iter1() + amount, - this->end_.iter1(), - this->begin_.iter2() + amount, - this->end_.iter2()}; - } - - auto take(blt::size_t amount) - { - return CompleteClass{this->begin_.iter1(), - this->begin_.iter1() + amount, - this->begin_.iter2(), - this->begin_.iter2() + amount}; - } - }; - - /** - * Reversible (bidirectional) base class for storing the begin/end iterators, operates in reverse for reverse iteration. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate (std::reverse_iterator). - * @tparam CompleteClass completed class returned from skip/take methods - * @tparam CompleteClassRev reverse version of CompleteClass, returned from rev - */ - template - class iterator_storage_reversible_rev : public iterator_storage_reversible - { - public: - using iterator_storage_reversible::iterator_storage_reversible; - - auto rev() const - { - return CompleteClass{this->end_.base().iter1(), - this->begin_.base().iter1(), - this->end_.base().iter2(), - this->begin_.base().iter2()}; - } - - auto skip(blt::size_t amount) - { - auto begin = this->begin_.base(); - for (blt::size_t i = 0; i < amount; i++) - --begin; - return CompleteClassRev{begin.iter1(), - this->end_.base().iter1(), - begin.iter2(), - this->end_.base().iter2()}; - } - - auto take(blt::size_t amount) - { - auto end = this->begin_.base(); - for (blt::size_t i = 0; i < amount; i++) - --end; - return CompleteClassRev{ - this->begin_.base().iter1(), - end.iter1(), - this->begin_.base().iter2(), - end.iter2()}; - } - }; - - /** - * Random access base class for storing the begin/end iterator. - * Has updated skip and take methods which make use of the random access nature of the iterator. - * Operates in reverse for reverse iteration. - * @tparam Iter iterator type. - * @tparam IterWrapper wrapper used to iterate (std::reverse_iterator). - * @tparam CompleteClass completed class returned from skip/take methods - * @tparam CompleteClassRev reverse version of CompleteClass, returned from rev - */ - template - class iterator_storage_random_access_rev : public iterator_storage_reversible_rev - { - public: - using iterator_storage_reversible_rev::iterator_storage_reversible_rev; - - auto skip(blt::size_t amount) - { - return CompleteClassRev{this->begin_.base().iter1() - amount, - this->end_.base().iter1(), - this->begin_.base().iter2() - amount, - this->end_.base().iter2()}; - } - - auto take(blt::size_t amount) - { - return CompleteClassRev{this->begin_.base().iter1(), - this->begin_.base().iter1() - amount, - this->begin_.base().iter2(), - this->begin_.base().iter2() - amount}; - } - }; - - /** - * Base class for types which can be converted to an enumerator - */ - template - class enumerator_convertible - { - public: - auto enumerate() - { - auto* b = static_cast(this); - return CompleteEnumerator{b->begin(), b->end(), static_cast(std::distance(b->begin(), b->end()))}; - } - }; + return iterator::iterator_container{container.begin(), container.end()}; } - /** - * Enumerator specialization for forward iterators - */ - template - class enumerator, std::void_t>> - : public iterator::iterator_storage_base, enumerator> + template + static inline auto iterate(const T& container) { - public: - explicit enumerator(Iter begin, Iter end, blt::size_t container_size): - iterator::iterator_storage_base, enumerator> - {iterator::enumerate_wrapper{std::move(begin), 0}, - iterator::enumerate_wrapper{std::move(end), container_size}} - {} - - explicit enumerator(Iter begin, Iter end, blt::size_t begin_index, blt::size_t end_index): - iterator::iterator_storage_base, enumerator>{ - iterator::enumerate_wrapper{std::move(begin), begin_index}, - iterator::enumerate_wrapper{std::move(end), end_index}} - {} - }; - - /** - * Enumerator specialization for bidirectional iterators - */ - template - class enumerator, std::void_t>> - : public iterator::iterator_storage_reversible, enumerator, enumerator_rev> - { - public: - explicit enumerator(Iter begin, Iter end, blt::size_t container_size): - iterator::iterator_storage_reversible, enumerator, enumerator_rev> - {iterator::enumerate_wrapper{std::move(begin), 0}, - iterator::enumerate_wrapper{std::move(end), container_size}} - {} - - explicit enumerator(Iter begin, Iter end, blt::size_t begin_index, blt::size_t end_index): - iterator::iterator_storage_reversible, enumerator, enumerator_rev>{ - iterator::enumerate_wrapper{std::move(begin), begin_index}, - iterator::enumerate_wrapper{std::move(end), end_index}} - {} - }; - - /** - * Enumerator specialization for random access iterators - */ - template - class enumerator, std::void_t>> - : public iterator::iterator_storage_random_access, enumerator, enumerator_rev> - { - public: - explicit enumerator(Iter begin, Iter end, blt::size_t container_size): - iterator::iterator_storage_random_access, enumerator, enumerator_rev> - {iterator::enumerate_wrapper{std::move(begin), 0}, - iterator::enumerate_wrapper{std::move(end), container_size}} - {} - - explicit enumerator(Iter begin, Iter end, blt::size_t begin_index, blt::size_t end_index): - iterator::iterator_storage_random_access, enumerator, enumerator_rev>{ - iterator::enumerate_wrapper{std::move(begin), begin_index}, - iterator::enumerate_wrapper{std::move(end), end_index}} - {} - }; - - /** - * Reverse enumerator specialization for bidirectional iterators - */ - template - class enumerator_rev, std::void_t>> - : public iterator::iterator_storage_reversible_rev>, enumerator, enumerator_rev> - { - public: - explicit enumerator_rev(Iter begin, Iter end, blt::size_t container_size): - iterator::iterator_storage_reversible_rev>, enumerator, enumerator_rev> - {std::reverse_iterator>{iterator::enumerate_wrapper{std::move(begin), 0}}, - std::reverse_iterator>{ - iterator::enumerate_wrapper{std::move(end), container_size}}} - {} - - explicit enumerator_rev(Iter begin, Iter end, blt::size_t begin_index, blt::size_t end_index): - iterator::iterator_storage_reversible_rev>, enumerator, enumerator_rev>{ - std::reverse_iterator>{ - iterator::enumerate_wrapper{std::move(begin), begin_index}}, - std::reverse_iterator>{iterator::enumerate_wrapper{std::move(end), end_index}}} - {} - }; - - /** - * Reverse enumerator specialization for random access iterators - */ - template - class enumerator_rev, std::void_t>> - : public iterator::iterator_storage_random_access_rev>, enumerator, enumerator_rev> - { - public: - explicit enumerator_rev(Iter begin, Iter end, blt::size_t container_size): - iterator::iterator_storage_random_access_rev>, enumerator, enumerator_rev> - {std::reverse_iterator>{iterator::enumerate_wrapper{std::move(begin), 0}}, - std::reverse_iterator>{ - iterator::enumerate_wrapper{std::move(end), container_size}}} - {} - - explicit enumerator_rev(Iter begin, Iter end, blt::size_t begin_index, blt::size_t end_index): - iterator::iterator_storage_random_access_rev>, enumerator, enumerator_rev>{ - std::reverse_iterator>{ - iterator::enumerate_wrapper{std::move(begin), begin_index}}, - std::reverse_iterator>{iterator::enumerate_wrapper{std::move(end), end_index}}} - {} - }; - - // CTAD for enumerators - - template - enumerator(Iter, Iter) -> enumerator; - - template - enumerator(Iter, Iter, blt::size_t) -> enumerator; - - template - enumerator(Iter, Iter, blt::size_t, blt::size_t) -> enumerator; - - template - class pair_iterator>, - std::void_t>> - : public iterator::iterator_storage_base, pair_iterator>, - public iterator::enumerator_convertible, enumerator>> - { - public: - explicit pair_iterator(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2): - iterator::iterator_storage_base, pair_iterator> - {iterator::pair_wrapper{std::move(begin1), std::move(begin2)}, - iterator::pair_wrapper{std::move(end1), std::move(end2)}} - {} - }; - - template - class pair_iterator>, - std::void_t>> - : public iterator::iterator_storage_reversible, pair_iterator, pair_iterator_rev>, - public iterator::enumerator_convertible, enumerator>> - { - public: - explicit pair_iterator(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2): - iterator::iterator_storage_reversible, pair_iterator, pair_iterator_rev> - {iterator::pair_wrapper{std::move(begin1), std::move(begin2)}, - iterator::pair_wrapper{std::move(end1), std::move(end2)}} - {} - }; - - template - class pair_iterator>, - std::void_t>> - : public iterator::iterator_storage_random_access, pair_iterator, pair_iterator_rev>, - public iterator::enumerator_convertible, enumerator>> - { - public: - explicit pair_iterator(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2): - iterator::iterator_storage_random_access, pair_iterator, pair_iterator_rev> - {iterator::pair_wrapper{std::move(begin1), std::move(begin2)}, - iterator::pair_wrapper{std::move(end1), std::move(end2)}} - {} - }; - - template - class pair_iterator_rev>, - std::void_t>> - : public iterator::iterator_storage_reversible_rev>, pair_iterator, pair_iterator_rev>, - public iterator::enumerator_convertible, enumerator>> - { - public: - explicit pair_iterator_rev(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2): - iterator::iterator_storage_reversible_rev>, pair_iterator, pair_iterator_rev> - {std::reverse_iterator>{ - iterator::pair_wrapper{std::move(begin1), std::move(begin2)}}, - std::reverse_iterator>{ - iterator::pair_wrapper{std::move(end1), std::move(end2)}}} - {} - }; - - template - class pair_iterator_rev>, - std::void_t>> - : public iterator::iterator_storage_random_access_rev>, pair_iterator, pair_iterator_rev>, - public iterator::enumerator_convertible, enumerator>> - { - public: - explicit pair_iterator_rev(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2): - iterator::iterator_storage_random_access_rev>, pair_iterator, pair_iterator_rev> - {std::reverse_iterator>{ - iterator::pair_wrapper{std::move(begin1), std::move(begin2)}}, - std::reverse_iterator>{ - iterator::pair_wrapper{std::move(end1), std::move(end2)}}} - {} - }; - - // CTAD for pair iterators - - template - pair_iterator(Iter1, Iter1, Iter2, Iter2) -> pair_iterator; - - template - static inline auto enumerate(const T(& container)[size]) - { - return enumerator{&container[0], &container[size], size}; + return iterator::iterator_container{container.begin(), container.end()}; } template - static inline auto enumerate(T(& container)[size]) + static inline auto iterate(const T(& container)[size]) { - return enumerator{&container[0], &container[size], size}; + return iterator::iterator_container{&container[0], &container[size]}; } - template - static inline auto enumerate(T& container) + template + static inline auto iterate(T(& container)[size]) { - return enumerator{container.begin(), container.end(), container.size()}; + return iterator::iterator_container{&container[0], &container[size]}; } - - template - static inline auto enumerate(T&& container) - { - return enumerator{container.begin(), container.end(), container.size()}; - } - - template - static inline auto enumerate(const T& container) - { - return enumerator{container.begin(), container.end(), container.size()}; - } - - template - static inline auto in_pairs(const T& container1, const G& container2) - { - return pair_iterator{container1.begin(), container1.end(), container2.begin(), container2.end()}; - } - - template - static inline auto in_pairs(T& container1, G& container2) - { - return pair_iterator{container1.begin(), container1.end(), container2.begin(), container2.end()}; - } - - template - static inline auto in_pairs(const T(& container1)[size], const G(& container2)[size]) - { - return pair_iterator{&container1[0], &container1[size], &container2[0], &container2[size]}; - } - - template - static inline auto in_pairs(T(& container1)[size], G(& container2)[size]) - { - return pair_iterator{&container1[0], &container1[size], &container2[0], &container2[size]}; - } - - template - static inline auto in_pairs(T&& container1, G&& container2) - { - return pair_iterator{container1.begin(), container1.end(), container2.begin(), container2.end()}; - } - + } #endif //BLT_ITERATOR_H diff --git a/include/blt/iterator/zip.h b/include/blt/iterator/zip.h index 1fec30d..bc60275 100644 --- a/include/blt/iterator/zip.h +++ b/include/blt/iterator/zip.h @@ -20,8 +20,6 @@ #define BLT_ITERATOR_ZIP #include -#include -#include #include namespace blt @@ -57,21 +55,20 @@ namespace blt zip_wrapper& operator--() { + static_assert(meta::is_bidirectional_or_better_category_v, "Iterator must be bidirectional or better!"); std::apply([](auto& ... i) { ((--i), ...); }, this->iter); return *this; } friend zip_wrapper operator+(const zip_wrapper& a, blt::ptrdiff_t n) { - static_assert(std::is_same_v, - "Iterator must allow random access"); + static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return std::apply([n](auto& ... i) { return zip_wrapper((i + n)...); }, a.iter); } friend zip_wrapper operator-(const zip_wrapper& a, blt::ptrdiff_t n) { - static_assert(std::is_same_v, - "Iterator must allow random access"); + static_assert(meta::is_random_access_iterator_category_v, "Iterator must allow random access"); return std::apply([n](auto& ... i) { return zip_wrapper((i - n)...); }, a.iter); } @@ -97,56 +94,44 @@ namespace blt return min; } }; - -// template -// struct zip_wrapper : public Iter -// { -// 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; -// -// using Iter::Iter; -// }; + + template + struct iterator_pair + { + using type = Iter; + + iterator_pair(Iter begin, Iter end): begin(std::move(begin)), end(std::move(end)) + {} + + Iter begin; + Iter end; + }; } - template - struct iterator_pair - { - using type = Iter; - - iterator_pair(Iter begin, Iter end): begin(std::move(begin)), end(std::move(end)) - {} - - Iter begin; - Iter end; - }; - template class zip_iterator_container : public iterator::iterator_container> { public: using iterator::iterator_container>::iterator_container; - explicit zip_iterator_container(iterator_pair... iterator_pairs): + explicit zip_iterator_container(iterator::iterator_pair... iterator_pairs): iterator::iterator_container>(iterator::zip_wrapper{std::move(iterator_pairs.begin)...}, iterator::zip_wrapper{std::move(iterator_pairs.end)...}) {} }; - namespace impl + namespace iterator::impl { template class zip_t { public: template - auto zip(iterator_pair... iterator_pairs) + auto zip(iterator::iterator_pair... iterator_pairs) { auto* d = static_cast(this); - return zip_iterator_container(iterator_pairbegin())>{d->begin(), d->end()}, iterator_pairs...); + return zip_iterator_container(iterator::iterator_pairbegin())>{d->begin(), d->end()}, iterator_pairs...); } }; } @@ -156,7 +141,7 @@ namespace blt */ template - zip_iterator_container(iterator_pair...) -> zip_iterator_container; + zip_iterator_container(iterator::iterator_pair...) -> zip_iterator_container; template zip_iterator_container(std::initializer_list...) -> zip_iterator_container; @@ -169,8 +154,43 @@ namespace blt template auto zip(Container& ... container) { - return zip_iterator_container{iterator_pair{container.begin(), container.end()}...}; + return zip_iterator_container{iterator::iterator_pair{std::begin(container), std::end(container)}...}; } + + template + auto zip(const Container& ... container) + { + return zip_iterator_container{iterator::iterator_pair{std::begin(container), std::end(container)}...}; + } + + template + static inline auto in_pairs(const T& container1, const G& container2) + { + return zip_iterator_container{iterator::iterator_pair{container1.begin(), container1.end()}, + iterator::iterator_pair{container2.begin(), container2.end()}}; + } + + template + static inline auto in_pairs(T& container1, G& container2) + { + return zip_iterator_container{iterator::iterator_pair{container1.begin(), container1.end()}, + iterator::iterator_pair{container2.begin(), container2.end()}}; + } + + template + static inline auto in_pairs(const T(& container1)[size], const G(& container2)[size]) + { + return zip_iterator_container{iterator::iterator_pair{&container1[0], &container1[size]}, + iterator::iterator_pair{&container2[0], &container2[size]}}; + } + + template + static inline auto in_pairs(T(& container1)[size], G(& container2)[size]) + { + return zip_iterator_container{iterator::iterator_pair{&container1[0], &container1[size]}, + iterator::iterator_pair{&container2[0], &container2[size]}}; + } + } #endif //BLT_ITERATOR_ZIP diff --git a/include/blt/meta/iterator.h b/include/blt/meta/iterator.h index e7df5a7..7a081bd 100644 --- a/include/blt/meta/iterator.h +++ b/include/blt/meta/iterator.h @@ -122,7 +122,8 @@ namespace blt::meta template struct is_reverse_iterator> : std::true_type - {}; + { + }; template inline constexpr bool is_reverse_iterator_v = is_reverse_iterator::value; diff --git a/include/blt/std/ranges.h b/include/blt/std/ranges.h index 1e8693b..87c0538 100644 --- a/include/blt/std/ranges.h +++ b/include/blt/std/ranges.h @@ -19,151 +19,6 @@ namespace blt { - namespace itr - { - template - class itr_container - { - public: - itr_container(Begin&& begin, End&& end): begin_(std::forward(begin)), end_(std::forward(end)) - {} - - Begin begin() - { - return begin_; - } - - End end() - { - return end_; - } - - private: - Begin begin_; - End end_; - }; - - // TODO: cleanup! all of this! add support for reversing - template - class pair_iterator - { - public: - using c1_ref = blt::meta::deref_return_t; - using c2_ref = blt::meta::deref_return_t; - - using iterator_category = std::forward_iterator_tag; - using value_type = std::pair; - using difference_type = blt::ptrdiff_t; - using pointer = void*; - using reference = value_type&; - using const_reference = const value_type&; - - explicit pair_iterator(C1_TYPE c1, C2_TYPE c2): current_c1_iter(c1), current_c2_iter(c2) - {} - - pair_iterator& operator++() - { - ++current_c1_iter; - ++current_c2_iter; - return *this; - } - - bool operator==(pair_iterator other) const - { - return current_c1_iter == other.current_c1_iter && current_c2_iter == other.current_c2_iter; - } - - bool operator!=(pair_iterator other) const - { - return current_c1_iter != other.current_c1_iter || current_c2_iter != other.current_c2_iter; - } - - value_type operator*() const - { - return {*current_c1_iter, *current_c2_iter}; - }; - - value_type operator*() - { - return {*current_c1_iter, *current_c2_iter}; - }; - - private: - C1_TYPE current_c1_iter; - C2_TYPE current_c2_iter; - }; - } - - template - static inline auto iterate(Begin&& begin, End&& end) - { - return itr::itr_container{std::forward(begin), std::forward(end)}; - } - - template - static inline auto reverse_iterate(Begin&& begin, End&& end) - { - return itr::itr_container{std::reverse_iterator(std::forward(end)), std::reverse_iterator(std::forward(begin))}; - } - - template typename iterator = itr::pair_iterator> - class pair_enumerator - { - public: - explicit pair_enumerator(C1_ITER c1_begin, C1_ITER c1_end, C2_ITER c2_begin, C2_ITER c2_end): - begin_(std::move(c1_begin), std::move(c2_begin)), end_(std::move(c1_end), std::move(c2_end)) - { - auto size_c1 = c1_end - c1_begin; - auto size_c2 = c2_end - c2_begin; - if (size_c1 != size_c2) - throw std::runtime_error("Iterator sizes don't match!"); - } - - iterator begin() - { - return begin_; - } - - iterator end() - { - return end_; - } - - private: - iterator begin_; - iterator end_; - }; - -// template -// static inline auto in_pairs(const T& container1, const G& container2) -// { -// return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; -// } -// -// template -// static inline auto in_pairs(T& container1, G& container2) -// { -// return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; -// } -// -// template -// static inline auto in_pairs(const T(& container1)[size], const G(& container2)[size]) -// { -// return pair_enumerator{&container1[0], &container1[size], &container2[0], &container2[size]}; -// } -// -// template -// static inline auto in_pairs(T(& container1)[size], G(& container2)[size]) -// { -// return pair_enumerator{&container1[0], &container1[size], &container2[0], &container2[size]}; -// } -// -// template -// static inline auto in_pairs(T&& container1, G&& container2) -// { -// return pair_enumerator{container1.begin(), container1.end(), container2.begin(), container2.end()}; -// } - template struct range { @@ -239,41 +94,6 @@ namespace blt } }; - template - class itr_offset - { - private: - I begin_; - I end_; - public: - template - itr_offset(I begin, I end, T offset): begin_(begin), end_(end) - { - for (T t = 0; t < offset; t++) - ++begin_; - } - - template - itr_offset(C& container, T offset): begin_(container.begin()), end_(container.end()) - { - for (T t = 0; t < offset; t++) - ++begin_; - } - - auto begin() - { - return begin_; - } - - auto end() - { - return end_; - } - }; - - template - itr_offset(C, T) -> itr_offset; - inline constexpr std::size_t dynamic_extent = std::numeric_limits::max(); template diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index 63acc33..7ef2e73 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit 63acc3336f941c6f324c88eb9ee4ce623a460cd5 +Subproject commit 7ef2e733416953b222851f9a360d7fc72d068ee5 diff --git a/tests/iterator_tests.cpp b/tests/iterator_tests.cpp index 2cc275a..183be9b 100644 --- a/tests/iterator_tests.cpp +++ b/tests/iterator_tests.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -122,6 +123,10 @@ void test_enumerate() void test_pairs() { blt::log_box_t box(std::cout, "Pairs Tests", 25); + for (auto [a1, a2] : blt::in_pairs(array_1, array_2)) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << "\n"; + } } void test_zip() @@ -158,6 +163,41 @@ void test_zip() } } +void test_iterate() +{ + blt::log_box_t box(std::cout, "Iterate Tests", 25); + for (auto v : blt::iterate(array_1)) + { + BLT_TRACE_STREAM << "Element: " << v << "\n"; + } + BLT_TRACE("================================"); + for (auto v : blt::iterate(array_1).skip(5)) + { + BLT_TRACE_STREAM << "Element: " << v << "\n"; + } + BLT_TRACE("================================"); + for (auto v : blt::iterate(array_1).take(5)) + { + BLT_TRACE_STREAM << "Element: " << v << "\n"; + } + BLT_TRACE("================================"); + for (auto v : blt::iterate(array_1).rev()) + { + BLT_TRACE_STREAM << "Element: " << v << "\n"; + } + BLT_TRACE("================================"); + for (auto [a, b] : blt::iterate(array_1).zip(list_1)) + { + BLT_TRACE_STREAM << "Zip: " << a << " " << b << "\n"; + } + BLT_TRACE("================================"); + for (auto [i, data] : blt::iterate(array_1).zip(list_1).skip(3).take(4).enumerate()) + { + auto [a, b] = data; + BLT_TRACE_STREAM << "Zip (" << i << "): " << a << " " << b << "\n"; + } +} + int main() { test_enumerate(); @@ -165,4 +205,6 @@ int main() test_pairs(); std::cout << std::endl; test_zip(); + std::cout << std::endl; + test_iterate(); } \ No newline at end of file