diff --git a/CMakeLists.txt b/CMakeLists.txt index 6336797..a25f735 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.0.6) +set(BLT_VERSION 1.1.1) set(BLT_TARGET BLT) diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h new file mode 100644 index 0000000..6fa91b8 --- /dev/null +++ b/include/blt/iterator/common.h @@ -0,0 +1,130 @@ +#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::iterator +{ + template + struct wrapper_base + { + wrapper_base operator++(int) + { + auto tmp = *this; + ++*this; + return tmp; + } + + wrapper_base operator--(int) + { + static_assert(std::is_same_v || + std::is_same_v, + "Iterator must allow random access"); + auto tmp = *this; + --*this; + return tmp; + } + + auto operator[](blt::ptrdiff_t n) const + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return *(*this + n); + } + + 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 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) + { + 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) + { + static_assert(std::is_same_v, + "Iterator must allow random access"); + return b < a; + } + + friend bool operator>=(const wrapper_base& a, wrapper_base& 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) + { + 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) + { + return a.base() == b.base(); + } + + friend bool operator!=(const wrapper_base& a, const wrapper_base& b) + { + return !(a.base() == b.base()); // NOLINT + } + }; +} + +#endif //BLT_ITERATOR_ITER_COMMON 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 51c4cfc..96400eb 100644 --- a/include/blt/iterator/iterator.h +++ b/include/blt/iterator/iterator.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/blt/iterator/zip.h b/include/blt/iterator/zip.h index b4e6efb..f5fd24b 100644 --- a/include/blt/iterator/zip.h +++ b/include/blt/iterator/zip.h @@ -19,7 +19,7 @@ #ifndef BLT_ITERATOR_ZIP #define BLT_ITERATOR_ZIP -#include +#include #include #include #include @@ -28,14 +28,11 @@ namespace blt { namespace iterator { - template - class zip_wrapper; - template - class zip_wrapper + class zip_wrapper : public wrapper_base> { public: - using iterator_category = std::input_iterator_tag; + using iterator_category = meta::lowest_iterator_category_t; using value_type = std::tuple...>; using difference_type = blt::ptrdiff_t; using pointer = value_type; @@ -49,99 +46,18 @@ namespace blt return std::apply([](auto& ... i) { return std::tuple...>{*i...}; }, iter); } - friend bool operator==(const zip_wrapper& a, const zip_wrapper& b) - { - return a.iter == b.iter; - } - - friend bool operator!=(const zip_wrapper& a, const zip_wrapper& b) - { - return !(a.iter == b.iter); - } - zip_wrapper& operator++() { std::apply([](auto& ... i) { ((++i), ...); }, iter); return *this; } - zip_wrapper operator++(int) - { - auto tmp = *this; - ++*this; - return tmp; - } - - auto raw_tuple() - { - return iter; - } - - protected: - std::tuple iter; - }; - - template - class zip_wrapper : public zip_wrapper - { - public: - using iterator_category = std::forward_iterator_tag; - using value_type = std::tuple...>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - - using zip_wrapper::zip_wrapper; - }; - - template - class zip_wrapper : public zip_wrapper - { - public: - using iterator_category = std::bidirectional_iterator_tag; - using value_type = std::tuple...>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - public: - using zip_wrapper::zip_wrapper; - zip_wrapper& operator--() { std::apply([](auto& ... i) { ((--i), ...); }, this->iter); return *this; } - zip_wrapper operator--(int) - { - auto tmp = *this; - --*this; - return tmp; - } - }; - - template - class zip_wrapper : public zip_wrapper - { - public: - using iterator_category = std::random_access_iterator_tag; - using value_type = std::tuple...>; - using difference_type = blt::ptrdiff_t; - using pointer = value_type; - using reference = value_type; - private: - template - static blt::ptrdiff_t sub(const zip_wrapper& a, const zip_wrapper& b, - std::integer_sequence) - { - blt::ptrdiff_t min = std::numeric_limits::max(); - ((min = std::min(min, std::get(a.iter) - std::get(b.iter))), ...); - return min; - } - - public: - using zip_wrapper::zip_wrapper; - zip_wrapper& operator+=(blt::ptrdiff_t n) { std::apply([n](auto& ... i) { ((i += n), ...); }, this->iter); @@ -154,54 +70,26 @@ namespace blt return *this; } - friend zip_wrapper operator+(const zip_wrapper& a, blt::ptrdiff_t n) - { - return std::apply([n](auto& ... i) { return zip_wrapper{(i + n)...}; }, a.iter); - } - - friend zip_wrapper operator+(blt::ptrdiff_t n, const zip_wrapper& a) - { - 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) - { - return std::apply([n](auto& ... i) { return zip_wrapper{(i - n)...}; }, a.iter); - } - - friend zip_wrapper operator-(blt::ptrdiff_t n, const zip_wrapper& a) - { - 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) { return sub(a, b, std::index_sequence_for()); } - auto operator[](blt::ptrdiff_t n) const + auto base() { - return *(*this + n); + return iter; } + + protected: + std::tuple iter; - friend bool operator<(const zip_wrapper& a, const zip_wrapper& b) + template + static blt::ptrdiff_t sub(const zip_wrapper& a, const zip_wrapper& b, + std::integer_sequence) { - return b - a > 0; - } - - friend bool operator>(const zip_wrapper& a, const zip_wrapper& b) - { - return b < a; - } - - friend bool operator>=(const zip_wrapper& a, const zip_wrapper& b) - { - return !(a < b); // NOLINT - } - - friend bool operator<=(const zip_wrapper& a, const zip_wrapper& b) - { - return !(a > b); // NOLINT + blt::ptrdiff_t min = std::numeric_limits::max(); + ((min = std::min(min, std::get(a.iter) - std::get(b.iter))), ...); + return min; } }; @@ -294,7 +182,8 @@ namespace blt { for (blt::size_t i = 0; i < n; i++) { - if constexpr (check){ + if constexpr (check) + { if (begin == end) break; } @@ -341,7 +230,7 @@ namespace blt m_begins(std::move(iterator_pairs.begin)...), m_ends(std::move(iterator_pairs.end)...) {} - zip_iterator_storage(iterator::zip_wrapper begins, iterator::zip_wrapper ends): + zip_iterator_storage(iterator::zip_wrapper begins, iterator::zip_wrapper ends): m_begins(std::move(begins)), m_ends(std::move(ends)) {} @@ -372,8 +261,8 @@ namespace blt } private: - iterator::zip_wrapper m_begins; - iterator::zip_wrapper m_ends; + iterator::zip_wrapper m_begins; + iterator::zip_wrapper m_ends; }; template @@ -389,8 +278,8 @@ namespace blt "reverse iteration is only supported on bidirectional or better iterators!"); } - zip_iterator_storage_rev(iterator::zip_wrapper begins, - iterator::zip_wrapper ends): m_begins(std::move(begins)), m_ends(std::move(ends)) + zip_iterator_storage_rev(iterator::zip_wrapper begins, + iterator::zip_wrapper ends): m_begins(std::move(begins)), m_ends(std::move(ends)) { static_assert((std::is_same_v || std::is_same_v), @@ -413,8 +302,8 @@ namespace blt } private: - std::reverse_iterator> m_begins; - std::reverse_iterator> m_ends; + std::reverse_iterator> m_begins; + std::reverse_iterator> m_ends; }; /* diff --git a/tests/iterator_tests.cpp b/tests/iterator_tests.cpp index e5a4a35..0ee82fc 100644 --- a/tests/iterator_tests.cpp +++ b/tests/iterator_tests.cpp @@ -126,17 +126,17 @@ void test_pairs() void test_zip() { blt::log_box_t box(std::cout, "Zip Tests", 25); - for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3)) + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1)) { BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; } BLT_TRACE("================================"); - for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3)) + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1).take(3)) { BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; } BLT_TRACE("================================"); - for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3).rev()) + for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1).take(3).rev()) { BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n"; }