From bac63ae815ec8cb222647f619b52bc33adbadc7b Mon Sep 17 00:00:00 2001 From: Brett Date: Fri, 28 Feb 2025 12:39:13 -0500 Subject: [PATCH] flatten, and flatten recursive. as_const doesn't work. --- CMakeLists.txt | 2 +- include/blt/iterator/common.h | 50 +++++++++++++++++++++++++++-- include/blt/iterator/flatten.h | 57 +++++++++++++++++++++++++++++----- include/blt/iterator/fwddecl.h | 5 ++- 4 files changed, 101 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dcdc9e9..b518054 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 4.0.34) +set(BLT_VERSION 4.0.35) set(BLT_TARGET BLT) diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h index 92a5b29..01e1f13 100644 --- a/include/blt/iterator/common.h +++ b/include/blt/iterator/common.h @@ -216,6 +216,34 @@ namespace blt::iterator Pred func; }; + template + class const_wrapper : public deref_only_wrapper> + { + public: + using ref_return = meta::deref_return_t; + + using iterator_category = typename std::iterator_traits::iterator_category; + using value_type = std::conditional_t, std::remove_reference_t, ref_return>; + using difference_type = ptrdiff_t; + using pointer = const value_type*; + using reference = const value_type&; + + explicit const_wrapper(Iter iter): deref_only_wrapper(std::move(iter)) + { + } + + auto operator*() const + { + if constexpr (std::is_reference_v) + { + return const_cast(*this->iter); + } else + { + return *this->iter; + } + } + }; + namespace impl { template @@ -385,9 +413,25 @@ namespace blt::iterator auto flatten() const { - return iterator_container>{ - blt::iterator::flatten_wrapper{m_begin}, - blt::iterator::flatten_wrapper{m_end} + return iterator_container>{ + blt::iterator::flatten_wrapper{m_begin}, + blt::iterator::flatten_wrapper{m_end} + }; + } + + auto flatten_all() const + { + return iterator_container>{ + blt::iterator::flatten_wrapper{m_begin}, + blt::iterator::flatten_wrapper{m_end} + }; + } + + auto as_const() const + { + return iterator_container>{ + const_wrapper{m_begin}, + const_wrapper{m_end} }; } diff --git a/include/blt/iterator/flatten.h b/include/blt/iterator/flatten.h index 79fdca3..28f3c61 100644 --- a/include/blt/iterator/flatten.h +++ b/include/blt/iterator/flatten.h @@ -28,34 +28,68 @@ namespace blt::iterator namespace detail { template - static auto flatten(Tuple&& tuple) -> decltype(auto) + static auto flatten_recursive(Tuple&& tuple) -> decltype(auto) { using Decay = std::decay_t; if constexpr (meta::is_tuple_v || meta::is_pair_v) { return std::apply([](auto&&... args) { - return std::tuple_cat(flatten(std::forward(args))...); + return std::tuple_cat(flatten_recursive(std::forward(args))...); }, std::forward(tuple)); - } else + } + else { if constexpr (std::is_lvalue_reference_v) { return std::forward_as_tuple(std::forward(tuple)); - } else + } + else { return std::make_tuple(std::forward(tuple)); } } } + + template + static auto ensure_tuple(Tuple&& tuple) -> decltype(auto) + { + using Decay = std::decay_t; + if constexpr (meta::is_tuple_v || meta::is_pair_v) + { + return std::forward(tuple); + } + else + { + if constexpr (std::is_lvalue_reference_v) + { + return std::forward_as_tuple(std::forward(tuple)); + } + else + { + return std::make_tuple(std::forward(tuple)); + } + } + } + + template + static auto flatten(Tuple&& tuple) -> decltype(auto) + { + return std::apply([](auto&&... args) + { + return std::tuple_cat(ensure_tuple(std::forward(args))...); + }, std::forward(tuple)); + } } - template - class flatten_wrapper : public deref_only_wrapper> + template + class flatten_wrapper : public deref_only_wrapper> { public: using iterator_category = typename std::iterator_traits::iterator_category; - using value_type = std::remove_reference_t()))>; + using value_type = std::conditional_t()))>, + std::remove_reference_t()))>>; using difference_type = ptrdiff_t; using pointer = value_type*; using reference = value_type&; @@ -67,7 +101,14 @@ namespace blt::iterator auto operator*() const -> decltype(auto) { - return detail::flatten(*this->iter); + if constexpr (Recursive) + { + return detail::flatten_recursive(*this->iter); + } + else + { + return detail::flatten(*this->iter); + } } }; } diff --git a/include/blt/iterator/fwddecl.h b/include/blt/iterator/fwddecl.h index 6fcf5b3..50f18f1 100644 --- a/include/blt/iterator/fwddecl.h +++ b/include/blt/iterator/fwddecl.h @@ -49,8 +49,11 @@ namespace blt template class filter_wrapper; - template + template class flatten_wrapper; + + template + class const_wrapper; namespace impl {