From a66fc586fd679aab7a7f9ffd683af450f30e7c82 Mon Sep 17 00:00:00 2001 From: Brett Laptop <tri11paragon@tpgc.me> Date: Mon, 30 Sep 2024 18:03:44 -0400 Subject: [PATCH] skip doesnt work --- CMakeLists.txt | 12 +-- include/blt/iterator/common.h | 198 ++++++++++++++++++++++++++++++++-- include/blt/iterator/zip.h | 173 ++--------------------------- libraries/parallel-hashmap | 2 +- tests/iterator_tests.cpp | 7 +- 5 files changed, 211 insertions(+), 181 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9da53f2..d0ebaf1 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.2) +set(BLT_VERSION 1.1.3) set(BLT_TARGET BLT) @@ -140,7 +140,7 @@ install(FILES ${CMAKE_BINARY_DIR}/config/blt/config.h DESTINATION ${CMAKE_INSTAL set_target_properties(${BLT_TARGET} PROPERTIES VERSION ${BLT_VERSION}) set_target_properties(${BLT_TARGET} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR}) if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND) - target_compile_options(${BLT_TARGET} PUBLIC -fuse-ld=mold) + target_link_options(${BLT_TARGET} PUBLIC -fuse-ld=mold) endif () install(TARGETS ${BLT_TARGET} @@ -154,16 +154,16 @@ macro(blt_add_project name source type) add_executable(${name}-${type} ${source}) + if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND) + add_link_options(-fuse-ld=mold) + endif () + target_link_libraries(${name}-${type} PRIVATE BLT) target_compile_options(${name}-${type} PRIVATE -Wall -Wextra -Wpedantic -Wno-comment) target_link_options(${name}-${type} PRIVATE -Wall -Wextra -Wpedantic -Wno-comment) target_compile_definitions(${name}-${type} PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL}) - if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND) - target_compile_options(${name}-${type} PUBLIC -fuse-ld=mold) - endif () - if (${TRACK_ALLOCATIONS}) target_compile_definitions(${name}-${type} PRIVATE BLT_TRACK_ALLOCATIONS=1) endif () diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h index 746af3c..12389dc 100644 --- a/include/blt/iterator/common.h +++ b/include/blt/iterator/common.h @@ -21,6 +21,7 @@ #include <type_traits> #include <iterator> +#include <blt/meta/meta.h> namespace blt::iterator { @@ -37,7 +38,8 @@ namespace blt::iterator base_wrapper operator--(int) { static_assert(std::is_same_v<typename Derived::iterator_category, std::bidirectional_iterator_tag> || - std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>, + std::is_same_v<typename Derived::iterator_category, + std::random_access_iterator_tag>, "Iterator must allow random access"); auto tmp = *this; --*this; @@ -86,27 +88,22 @@ namespace blt::iterator friend bool operator==(const base_wrapper& a, const base_wrapper& b) { - return a.base() == b.base(); + return static_cast<const Derived&>(a).base() == static_cast<const Derived&>(b).base(); } friend bool operator!=(const base_wrapper& a, const base_wrapper& b) { - return !(a.base() == b.base()); // NOLINT + return !(static_cast<const Derived&>(a).base() == static_cast<const Derived&>(b).base()); // NOLINT } }; - template<typename Iter, typename Derived> + template<typename Iter, typename Derived, bool dereference = false> struct passthrough_wrapper : public base_wrapper<Derived> { public: explicit passthrough_wrapper(Iter iter): iter(std::move(iter)) {} - meta::deref_return_t<Iter> operator*() const - { - return *iter; - } - auto base() const { return iter; @@ -118,8 +115,189 @@ namespace blt::iterator } protected: - Iter iter; + mutable Iter iter; }; + + template<typename Iter, typename Derived> + struct passthrough_wrapper<Iter, Derived, true> : public passthrough_wrapper<Iter, Derived> + { + using passthrough_wrapper<Iter, Derived>::passthrough_wrapper; + + meta::deref_return_t<Iter> operator*() const + { + return *this->iter; + } + }; + + namespace impls + { + template<typename Iter> + struct skip_wrapper : public passthrough_wrapper<Iter, skip_wrapper<Iter>> + { + public: + using iterator_category = typename std::iterator_traits<Iter>::iterator_category; + using value_type = typename std::iterator_traits<Iter>::value_type; + using difference_type = typename std::iterator_traits<Iter>::difference_type; + using pointer = typename std::iterator_traits<Iter>::pointer; + using reference = typename std::iterator_traits<Iter>::reference; + + explicit skip_wrapper(Iter iter, blt::size_t n): passthrough_wrapper<Iter, skip_wrapper<Iter>>(std::move(iter)), skip(n) + {} + + meta::deref_return_t<Iter> operator*() const + { + BLT_TRACE("Dereference Skip"); + forward_skip(); + return *this->iter; + } + + skip_wrapper& operator++() + { + BLT_TRACE("Forward Skip"); + forward_skip(); + ++this->iter; + return *this; + } + + skip_wrapper& operator--() + { + BLT_TRACE("Backward Skip"); + forward_skip(); + --this->iter; + return *this; + } + + friend skip_wrapper operator+(const skip_wrapper& a, blt::ptrdiff_t n) + { + static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>, + "Iterator must allow random access"); + return {a.base() + static_cast<blt::ptrdiff_t>(a.skip) + n, 0}; + } + + friend skip_wrapper operator-(const skip_wrapper& a, blt::ptrdiff_t n) + { + static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>, + "Iterator must allow random access"); + return {a.base() - static_cast<blt::ptrdiff_t>(a.skip) - n, 0}; + } + + private: + void forward_skip() const + { + if constexpr (std::is_same_v<iterator_category, std::random_access_iterator_tag>) + { + if (skip > 0) + { + this->iter = this->iter + skip; + skip = 0; + } + } else + { + while (skip > 0) + { + ++this->iter; + --skip; + } + } + } + + mutable blt::size_t skip; + }; + + template<typename Derived> + class take_t + { + private: + template<bool check> + auto take_base(blt::size_t n) + { + static_assert(!std::is_same_v<typename Derived::iterator_category, std::input_iterator_tag>, + "Cannot .take() on an input iterator!"); + auto* d = static_cast<Derived*>(this); + auto begin = d->begin(); + auto end = d->end(); + + // take variant for forward and bidirectional iterators + if constexpr (std::is_same_v<typename Derived::iterator_category, std::forward_iterator_tag> || + std::is_same_v<typename Derived::iterator_category, std::bidirectional_iterator_tag>) + { + // 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 (std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>) + { + // random access iterators can have math directly applied to them. + if constexpr (check) + { + return Derived{begin, begin + std::min(static_cast<blt::ptrdiff_t>(n), std::distance(begin, end))}; + } else + { + return Derived{begin, begin + n}; + } + } + } + + public: + auto take(blt::size_t n) + { return take_base<false>(n); } + + auto take_or(blt::size_t n) + { return take_base<true>(n); } + }; + } + + template<typename IterBase> + class iterator_container : public impls::take_t<iterator_container<IterBase>> + { + public: + using iterator_category = typename IterBase::iterator_category; + + iterator_container(IterBase begin, IterBase end): m_begin(std::move(begin)), m_end(std::move(end)) + {} + + template<typename Iter> + iterator_container(Iter&& begin, Iter&& end): m_begin(std::forward<Iter>(begin)), m_end(std::forward<Iter>(end)) + {} + + auto rev() + { + static_assert((std::is_same_v<typename IterBase::iterator_category, std::bidirectional_iterator_tag> || + std::is_same_v<typename IterBase::iterator_category, std::random_access_iterator_tag>), + ".rev() must be used with bidirectional (or better) iterators!"); + return iterator_container<std::reverse_iterator<IterBase>>{std::reverse_iterator<IterBase>{end()}, + std::reverse_iterator<IterBase>{begin()}}; + } + + auto skip(blt::size_t n) + { + return iterator_container<impls::skip_wrapper<IterBase>>{impls::skip_wrapper<IterBase>{begin(), n}, + impls::skip_wrapper<IterBase>{end(), n}}; + } + + auto begin() const + { + return m_begin; + } + + auto end() const + { + return m_end; + } + + protected: + IterBase m_begin; + IterBase m_end; + }; + } #endif //BLT_ITERATOR_ITER_COMMON diff --git a/include/blt/iterator/zip.h b/include/blt/iterator/zip.h index 4efb86a..4a04d41 100644 --- a/include/blt/iterator/zip.h +++ b/include/blt/iterator/zip.h @@ -38,6 +38,9 @@ namespace blt using pointer = value_type; using reference = value_type; + explicit zip_wrapper(std::tuple<Iter...> iter): iter(std::move(iter)) + {} + explicit zip_wrapper(Iter... iter): iter(std::make_tuple(iter...)) {} @@ -77,7 +80,7 @@ namespace blt return sub(a, b, std::index_sequence_for<Iter...>()); } - auto base() + auto base() const { return iter; } @@ -94,80 +97,6 @@ namespace blt return min; } }; - - template<typename Iter, bool checked> - struct skip_wrapper : public passthrough_wrapper<Iter, skip_wrapper<Iter, checked>> - { - public: - using iterator_category = typename std::iterator_traits<Iter>::iterator_category; - using value_type = typename std::iterator_traits<Iter>::value_type; - using difference_type = typename std::iterator_traits<Iter>::difference_type; - using pointer = typename std::iterator_traits<Iter>::pointer; - using reference = typename std::iterator_traits<Iter>::reference; - - explicit skip_wrapper(Iter iter, blt::size_t n): passthrough_wrapper<Iter, skip_wrapper<Iter, checked>>(std::move(iter)), skip(n) - {} - - skip_wrapper& operator++() - { - if constexpr (std::is_same_v<iterator_category, std::random_access_iterator_tag>) - { - if (skip > 0) - { - this->base() += skip; - skip = 0; - } - } else - { - while (skip > 0) - { - ++this->base(); - --skip; - } - } - - ++this->base(); - return *this; - } - - skip_wrapper& operator--() - { - if constexpr (std::is_same_v<iterator_category, std::random_access_iterator_tag>) - { - 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_category, std::random_access_iterator_tag>, - "Iterator must allow random access"); - return {a.base() + static_cast<blt::ptrdiff_t>(a.skip) + n, 0}; - } - - friend skip_wrapper operator-(const skip_wrapper& a, blt::ptrdiff_t n) - { - static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>, - "Iterator must allow random access"); - return {a.base() - static_cast<blt::ptrdiff_t>(a.skip) - n, 0}; - } - - private: - blt::size_t skip; - }; } template<typename Iter> @@ -183,92 +112,15 @@ namespace blt }; template<typename... Iter> - class zip_iterator_storage; - - template<typename... Iter> - class zip_iterator_storage_rev; - - template<typename... Iter> - class zip_iterator_storage + class zip_iterator_storage : public iterator::iterator_container<iterator::zip_wrapper<Iter...>> { public: - using iterator_category = meta::lowest_iterator_category_t<Iter...>; - public: - zip_iterator_storage(iterator_pair<Iter>... iterator_pairs): - m_begins(std::move(iterator_pairs.begin)...), m_ends(std::move(iterator_pairs.end)...) + using iterator::iterator_container<iterator::zip_wrapper<Iter...>>::iterator_container; + + explicit zip_iterator_storage(iterator_pair<Iter>... iterator_pairs): + iterator::iterator_container<iterator::zip_wrapper<Iter...>>(iterator::zip_wrapper<Iter...>{std::move(iterator_pairs.begin)...}, + iterator::zip_wrapper<Iter...>{std::move(iterator_pairs.end)...}) {} - - zip_iterator_storage(iterator::zip_wrapper<Iter...> begins, iterator::zip_wrapper<Iter...> ends): - m_begins(std::move(begins)), m_ends(std::move(ends)) - {} - - auto rev() - { - static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> || - std::is_same_v<iterator_category, std::random_access_iterator_tag>), - ".rev() must be used with bidirectional (or better) iterators!"); - return zip_iterator_storage_rev{m_ends, m_begins}; - } - - auto skip(blt::size_t n) - { - - } - - auto begin() const - { - return m_begins; - } - - auto end() const - { - return m_ends; - } - - private: - iterator::zip_wrapper<Iter...> m_begins; - iterator::zip_wrapper<Iter...> m_ends; - }; - - template<typename... Iter> - class zip_iterator_storage_rev - { - public: - using iterator_category = meta::lowest_iterator_category_t<Iter...>; - public: - zip_iterator_storage_rev(iterator_pair<Iter>... iterator_pairs): m_begins(iterator_pairs.begin...), m_ends(iterator_pairs.end...) - { - static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> || - std::is_same_v<iterator_category, std::random_access_iterator_tag>), - "reverse iteration is only supported on bidirectional or better iterators!"); - } - - zip_iterator_storage_rev(iterator::zip_wrapper<Iter...> begins, - iterator::zip_wrapper<Iter...> ends): m_begins(std::move(begins)), m_ends(std::move(ends)) - { - static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> || - std::is_same_v<iterator_category, std::random_access_iterator_tag>), - "reverse iteration is only supported on bidirectional or better iterators!"); - } - - auto rev() - { - return zip_iterator_storage{m_ends.base(), m_begins.base()}; - } - - auto begin() const - { - return m_begins; - } - - auto end() const - { - return m_ends; - } - - private: - std::reverse_iterator<iterator::zip_wrapper<Iter...>> m_begins; - std::reverse_iterator<iterator::zip_wrapper<Iter...>> m_ends; }; /* @@ -281,11 +133,6 @@ namespace blt template<typename... Iter> zip_iterator_storage(std::initializer_list<Iter>...) -> zip_iterator_storage<Iter...>; - template<typename... Iter> - zip_iterator_storage_rev(iterator_pair<Iter>...) -> zip_iterator_storage_rev<Iter...>; - - template<typename... Iter> - zip_iterator_storage_rev(std::initializer_list<Iter>...) -> zip_iterator_storage_rev<Iter...>; /* * Helper functions for creating zip containers diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap index 93201da..7ef2e73 160000 --- a/libraries/parallel-hashmap +++ b/libraries/parallel-hashmap @@ -1 +1 @@ -Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3 +Subproject commit 7ef2e733416953b222851f9a360d7fc72d068ee5 diff --git a/tests/iterator_tests.cpp b/tests/iterator_tests.cpp index 0ee82fc..0fb5198 100644 --- a/tests/iterator_tests.cpp +++ b/tests/iterator_tests.cpp @@ -136,7 +136,7 @@ void test_zip() BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; } BLT_TRACE("================================"); - for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1).take(3).rev()) + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3).rev()) { BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; } @@ -150,6 +150,11 @@ void test_zip() { BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; } + BLT_TRACE("================================"); + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).skip(2).rev()) + { + BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; + } } int main()