flatten, and flatten recursive. as_const doesn't work.

v2
Brett 2025-02-28 12:39:13 -05:00
parent e48fdf0c86
commit bac63ae815
4 changed files with 101 additions and 13 deletions

View File

@ -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)

View File

@ -216,6 +216,34 @@ namespace blt::iterator
Pred func;
};
template <typename Iter>
class const_wrapper : public deref_only_wrapper<Iter, const_wrapper<Iter>>
{
public:
using ref_return = meta::deref_return_t<Iter>;
using iterator_category = typename std::iterator_traits<Iter>::iterator_category;
using value_type = std::conditional_t<std::is_reference_v<ref_return>, std::remove_reference_t<ref_return>, 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<Iter, const_wrapper>(std::move(iter))
{
}
auto operator*() const
{
if constexpr (std::is_reference_v<ref_return>)
{
return const_cast<const value_type&>(*this->iter);
} else
{
return *this->iter;
}
}
};
namespace impl
{
template <typename Derived>
@ -385,9 +413,25 @@ namespace blt::iterator
auto flatten() const
{
return iterator_container<flatten_wrapper<IterBase>>{
blt::iterator::flatten_wrapper<IterBase>{m_begin},
blt::iterator::flatten_wrapper<IterBase>{m_end}
return iterator_container<flatten_wrapper<IterBase, false>>{
blt::iterator::flatten_wrapper<IterBase, false>{m_begin},
blt::iterator::flatten_wrapper<IterBase, false>{m_end}
};
}
auto flatten_all() const
{
return iterator_container<flatten_wrapper<IterBase, true>>{
blt::iterator::flatten_wrapper<IterBase, true>{m_begin},
blt::iterator::flatten_wrapper<IterBase, true>{m_end}
};
}
auto as_const() const
{
return iterator_container<const_wrapper<IterBase>>{
const_wrapper<IterBase>{m_begin},
const_wrapper<IterBase>{m_end}
};
}

View File

@ -28,34 +28,68 @@ namespace blt::iterator
namespace detail
{
template <typename Tuple>
static auto flatten(Tuple&& tuple) -> decltype(auto)
static auto flatten_recursive(Tuple&& tuple) -> decltype(auto)
{
using Decay = std::decay_t<Tuple>;
if constexpr (meta::is_tuple_v<Decay> || meta::is_pair_v<Decay>)
{
return std::apply([](auto&&... args)
{
return std::tuple_cat(flatten(std::forward<decltype(args)>(args))...);
return std::tuple_cat(flatten_recursive(std::forward<decltype(args)>(args))...);
}, std::forward<Tuple>(tuple));
} else
}
else
{
if constexpr (std::is_lvalue_reference_v<Tuple>)
{
return std::forward_as_tuple(std::forward<Tuple>(tuple));
} else
}
else
{
return std::make_tuple(std::forward<Tuple>(tuple));
}
}
}
template <typename Tuple>
static auto ensure_tuple(Tuple&& tuple) -> decltype(auto)
{
using Decay = std::decay_t<Tuple>;
if constexpr (meta::is_tuple_v<Decay> || meta::is_pair_v<Decay>)
{
return std::forward<Tuple>(tuple);
}
else
{
if constexpr (std::is_lvalue_reference_v<Tuple>)
{
return std::forward_as_tuple(std::forward<Tuple>(tuple));
}
else
{
return std::make_tuple(std::forward<Tuple>(tuple));
}
}
}
template <typename Tuple>
static auto flatten(Tuple&& tuple) -> decltype(auto)
{
return std::apply([](auto&&... args)
{
return std::tuple_cat(ensure_tuple(std::forward<decltype(args)>(args))...);
}, std::forward<Tuple>(tuple));
}
}
template <typename Iter>
class flatten_wrapper : public deref_only_wrapper<Iter, flatten_wrapper<Iter>>
template <typename Iter, bool Recursive>
class flatten_wrapper : public deref_only_wrapper<Iter, flatten_wrapper<Iter, Recursive>>
{
public:
using iterator_category = typename std::iterator_traits<Iter>::iterator_category;
using value_type = std::remove_reference_t<decltype(detail::flatten(*std::declval<Iter>()))>;
using value_type = std::conditional_t<Recursive,
std::remove_reference_t<decltype(detail::flatten_recursive(*std::declval<Iter>()))>,
std::remove_reference_t<decltype(detail::flatten(*std::declval<Iter>()))>>;
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);
}
}
};
}

View File

@ -49,9 +49,12 @@ namespace blt
template<typename Iter, typename Pred>
class filter_wrapper;
template<typename Iter>
template<typename Iter, bool Recursive>
class flatten_wrapper;
template<typename Iter>
class const_wrapper;
namespace impl
{
template<typename Derived>