diff --git a/source/mijin/util/iterators.hpp b/source/mijin/util/iterators.hpp index 2aff82a..ac66334 100644 --- a/source/mijin/util/iterators.hpp +++ b/source/mijin/util/iterators.hpp @@ -360,6 +360,10 @@ struct MappingRange : RangeAdapter { return MappingIterator(base.end(), functor); } + + [[nodiscard]] bool empty() const noexcept { + return base.begin() == base.end(); + } }; template @@ -668,6 +672,100 @@ auto chain(TFirstRange&& firstRange, TSecondRange&& secondRange, TMoreRanges&&.. return chain(std::forward(firstRange), chain(std::forward(secondRange), std::forward(moreRanges)...)); } +template +struct TypeFilteringIterator +{ + using difference_type = std::ptrdiff_t; + using value_type = TType; + using pointer = std::remove_pointer_t*; + using reference = std::remove_reference_t&; + 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(*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) + { + return dynamic_cast(*base); + } + else + { + return dynamic_cast(&*base); + } + } +}; + +template +struct TypeFilteringRange : RangeAdapter +{ + using orig_value_type = typename std::iterator_traits()))>::value_type; + using value_type = TType; + + RangeRef iterable; + + auto begin() const noexcept + { + return TypeFilteringIterator(iterable.begin(), iterable.end()); + } + + auto end() const noexcept + { + return TypeFilteringIterator(iterable.end(), iterable.end()); + } +}; + +template +auto filterType(TIterable&& iterable) +{ + return TypeFilteringRange{ + .iterable = {std::forward(iterable)} + }; +} + template TAs collect(TIterable&& iterable) { @@ -770,6 +868,17 @@ auto operator|(TIterable&& iterable, Filter filterer) return filter(std::forward(iterable), std::move(filterer.predicate)); } +template +struct FilterType +{ +}; + +template +auto operator|(TIterable&& iterable, FilterType) +{ + return filterType(std::forward(iterable)); +} + template struct Xth {};