Added type filtering iterator.

This commit is contained in:
Patrick 2023-11-16 00:33:44 +01:00
parent 0b8772c952
commit 121e8a84f5

View File

@ -360,6 +360,10 @@ struct MappingRange : RangeAdapter
{
return MappingIterator(base.end(), functor);
}
[[nodiscard]] bool empty() const noexcept {
return base.begin() == base.end();
}
};
template<typename TIterable, typename TFunctor>
@ -668,6 +672,100 @@ auto chain(TFirstRange&& firstRange, TSecondRange&& secondRange, TMoreRanges&&..
return chain(std::forward<TFirstRange>(firstRange), chain(std::forward<TSecondRange>(secondRange), std::forward<TMoreRanges>(moreRanges)...));
}
template<typename TType, typename TIterator>
struct TypeFilteringIterator
{
using difference_type = std::ptrdiff_t;
using value_type = TType;
using pointer = std::remove_pointer_t<value_type>*;
using reference = std::remove_reference_t<value_type>&;
using iterator_category = std::bidirectional_iterator_tag; // TODO?
TIterator base;
TIterator end;
TypeFilteringIterator(TIterator base_, TIterator end_) noexcept : base(base_), end(end_) {
if (base != end && !isCastable()) {
++(*this);
}
}
TypeFilteringIterator(const TypeFilteringIterator&) noexcept = default;
TypeFilteringIterator(TypeFilteringIterator&&) noexcept = default;
TypeFilteringIterator& operator=(const TypeFilteringIterator&) noexcept = default;
TypeFilteringIterator& operator=(TypeFilteringIterator&&) noexcept = default;
reference operator*() const noexcept
{
return static_cast<reference>(*base);
}
TypeFilteringIterator& operator++() noexcept
{
do
{
++base;
} while (base != end && !isCastable());
return *this;
}
TypeFilteringIterator operator++(int) noexcept
{
FilteringIterator copy(*this);
++(*this);
return copy;
}
bool operator==(const TypeFilteringIterator& other) const noexcept
{
return base == other.base && end == other.end;
}
bool operator!=(const TypeFilteringIterator& other) const noexcept
{
return !(*this == other);
}
private:
bool isCastable() const
{
if constexpr (std::is_pointer_v<TType>)
{
return dynamic_cast<TType>(*base);
}
else
{
return dynamic_cast<TType*>(&*base);
}
}
};
template<typename TType, typename TIterable>
struct TypeFilteringRange : RangeAdapter
{
using orig_value_type = typename std::iterator_traits<decltype(std::begin(std::declval<TIterable>()))>::value_type;
using value_type = TType;
RangeRef<TIterable> iterable;
auto begin() const noexcept
{
return TypeFilteringIterator<TType, decltype(iterable.begin())>(iterable.begin(), iterable.end());
}
auto end() const noexcept
{
return TypeFilteringIterator<TType, decltype(iterable.begin())>(iterable.end(), iterable.end());
}
};
template<typename TType, typename TIterable>
auto filterType(TIterable&& iterable)
{
return TypeFilteringRange<TType, TIterable>{
.iterable = {std::forward<TIterable>(iterable)}
};
}
template<typename TAs, typename TIterable>
TAs collect(TIterable&& iterable)
{
@ -770,6 +868,17 @@ auto operator|(TIterable&& iterable, Filter<TFilter> filterer)
return filter(std::forward<TIterable>(iterable), std::move(filterer.predicate));
}
template<typename T>
struct FilterType
{
};
template<typename TIterable, typename T>
auto operator|(TIterable&& iterable, FilterType<T>)
{
return filterType<T>(std::forward<TIterable>(iterable));
}
template<std::size_t idx>
struct Xth {};