diff --git a/CMakeLists.txt b/CMakeLists.txt index 03cfa5e..5a835df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 0.20.16) +set(BLT_VERSION 0.20.17) set(BLT_TEST_VERSION 0.0.1) set(BLT_TARGET BLT) diff --git a/include/blt/std/ranges.h b/include/blt/std/ranges.h index 3de45b2..de1facc 100644 --- a/include/blt/std/ranges.h +++ b/include/blt/std/ranges.h @@ -43,27 +43,16 @@ namespace blt End end_; }; - template - class iterator_base - { - public: - using value_type = blt::meta::value_type_t>; - using difference_type = blt::meta::difference_t; - using pointer = blt::meta::pointer_t; - using reference = blt::meta::reference_t&>; - using const_reference = blt::meta::const_reference_t&>; - }; - template class iterator { public: - using iterator_category = std::input_iterator_tag; - using value_type = typename iterator_base::value_type; - using difference_type = typename iterator_base::difference_type; - using pointer = typename iterator_base::pointer; - using reference = typename iterator_base::reference; - using const_reference = typename iterator_base::const_reference; + using iterator_category = std::forward_iterator_tag; + 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 const_reference = const reference; private: blt::size_t index; TYPE_ITR current; @@ -104,16 +93,65 @@ namespace blt }; }; + template + class pair_iterator + { + public: + using c1_ref = typename std::iterator_traits::reference; + using c2_ref = typename std::iterator_traits::reference; + + 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 class reverse_iterator { public: - using iterator_category = std::input_iterator_tag; - using value_type = typename iterator_base::value_type; - using difference_type = typename iterator_base::difference_type; - using pointer = typename iterator_base::pointer; - using reference = typename iterator_base::reference; - using const_reference = typename iterator_base::const_reference; + using iterator_category = std::forward_iterator_tag; + 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 const_reference = const reference; private: blt::size_t index; TYPE_ITR current; @@ -155,6 +193,18 @@ namespace blt }; } + 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::iterator> class enumerator { @@ -211,16 +261,62 @@ namespace blt return enumerator{container.begin(), container.end()}; } - template - static inline auto iterate(Begin&& begin, End&& end) + template typename iterator = itr::pair_iterator> + class pair_enumerator { - return itr::itr_container{std::forward(begin), std::forward(end)}; + 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 reverse_iterate(Begin&& begin, End&& end) + template + static inline auto in_pairs(T& container1, G& container2) { - return itr::itr_container{std::reverse_iterator(std::forward(end)), std::reverse_iterator(std::forward(begin))}; + 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