flatten, and flatten recursive. as_const doesn't work.
parent
e48fdf0c86
commit
bac63ae815
|
@ -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)
|
||||
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -49,8 +49,11 @@ 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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue