flatten, and flatten recursive. as_const doesn't work.
parent
e48fdf0c86
commit
bac63ae815
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
include(cmake/color.cmake)
|
include(cmake/color.cmake)
|
||||||
set(BLT_VERSION 4.0.34)
|
set(BLT_VERSION 4.0.35)
|
||||||
|
|
||||||
set(BLT_TARGET BLT)
|
set(BLT_TARGET BLT)
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,34 @@ namespace blt::iterator
|
||||||
Pred func;
|
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
|
namespace impl
|
||||||
{
|
{
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
|
@ -385,9 +413,25 @@ namespace blt::iterator
|
||||||
|
|
||||||
auto flatten() const
|
auto flatten() const
|
||||||
{
|
{
|
||||||
return iterator_container<flatten_wrapper<IterBase>>{
|
return iterator_container<flatten_wrapper<IterBase, false>>{
|
||||||
blt::iterator::flatten_wrapper<IterBase>{m_begin},
|
blt::iterator::flatten_wrapper<IterBase, false>{m_begin},
|
||||||
blt::iterator::flatten_wrapper<IterBase>{m_end}
|
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
|
namespace detail
|
||||||
{
|
{
|
||||||
template <typename Tuple>
|
template <typename Tuple>
|
||||||
static auto flatten(Tuple&& tuple) -> decltype(auto)
|
static auto flatten_recursive(Tuple&& tuple) -> decltype(auto)
|
||||||
{
|
{
|
||||||
using Decay = std::decay_t<Tuple>;
|
using Decay = std::decay_t<Tuple>;
|
||||||
if constexpr (meta::is_tuple_v<Decay> || meta::is_pair_v<Decay>)
|
if constexpr (meta::is_tuple_v<Decay> || meta::is_pair_v<Decay>)
|
||||||
{
|
{
|
||||||
return std::apply([](auto&&... args)
|
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));
|
}, std::forward<Tuple>(tuple));
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if constexpr (std::is_lvalue_reference_v<Tuple>)
|
if constexpr (std::is_lvalue_reference_v<Tuple>)
|
||||||
{
|
{
|
||||||
return std::forward_as_tuple(std::forward<Tuple>(tuple));
|
return std::forward_as_tuple(std::forward<Tuple>(tuple));
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return std::make_tuple(std::forward<Tuple>(tuple));
|
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>
|
template <typename Iter, bool Recursive>
|
||||||
class flatten_wrapper : public deref_only_wrapper<Iter, flatten_wrapper<Iter>>
|
class flatten_wrapper : public deref_only_wrapper<Iter, flatten_wrapper<Iter, Recursive>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator_category = typename std::iterator_traits<Iter>::iterator_category;
|
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 difference_type = ptrdiff_t;
|
||||||
using pointer = value_type*;
|
using pointer = value_type*;
|
||||||
using reference = value_type&;
|
using reference = value_type&;
|
||||||
|
@ -67,7 +101,14 @@ namespace blt::iterator
|
||||||
|
|
||||||
auto operator*() const -> decltype(auto)
|
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>
|
template<typename Iter, typename Pred>
|
||||||
class filter_wrapper;
|
class filter_wrapper;
|
||||||
|
|
||||||
template<typename Iter>
|
template<typename Iter, bool Recursive>
|
||||||
class flatten_wrapper;
|
class flatten_wrapper;
|
||||||
|
|
||||||
|
template<typename Iter>
|
||||||
|
class const_wrapper;
|
||||||
|
|
||||||
namespace impl
|
namespace impl
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue