From a8d51ef8b780644011da8974d99c524e93fe75f3 Mon Sep 17 00:00:00 2001 From: Regina Pfeifer Date: Fri, 15 Feb 2019 21:54:58 +0100 Subject: cmRange: Add functions filter and transform --- Source/cmRange.h | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/Source/cmRange.h b/Source/cmRange.h index b6d161e..7ccb143 100644 --- a/Source/cmRange.h +++ b/Source/cmRange.h @@ -9,6 +9,122 @@ #include #include +namespace RangeIterators { + +template +class FilterIterator +{ +public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename std::iterator_traits::value_type; + using difference_type = typename std::iterator_traits::difference_type; + using pointer = typename std::iterator_traits::pointer; + using reference = typename std::iterator_traits::reference; + + FilterIterator(Iter b, Iter e, UnaryPredicate p) + : Cur(std::move(b)) + , End(std::move(e)) + , Pred(std::move(p)) + { + this->SatisfyPredicate(); + } + + FilterIterator& operator++() + { + ++this->Cur; + this->SatisfyPredicate(); + return *this; + } + + FilterIterator& operator--() + { + do { + --this->Cur; + } while (!this->Pred(*this->Cur)); + return *this; + } + + bool operator==(FilterIterator const& other) const + { + return this->Cur == other.Cur; + } + + bool operator!=(FilterIterator const& other) const + { + return !this->operator==(other); + } + + auto operator*() const -> decltype(*std::declval()) + { + return *this->Cur; + } + +private: + void SatisfyPredicate() + { + while (this->Cur != this->End && !this->Pred(*this->Cur)) { + ++this->Cur; + } + } + + Iter Cur; + Iter End; + UnaryPredicate Pred; +}; + +template +class TransformIterator +{ +public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = + typename std::remove_cv()(*std::declval()))>::type>::type; + using difference_type = typename std::iterator_traits::difference_type; + using pointer = value_type const*; + using reference = value_type const&; + + TransformIterator(Iter i, UnaryFunction f) + : Base(std::move(i)) + , Func(std::move(f)) + { + } + + TransformIterator& operator++() + { + ++this->Base; + return *this; + } + + TransformIterator& operator--() + { + --this->Base; + return *this; + } + + bool operator==(TransformIterator const& other) const + { + return this->Base == other.Base; + } + + bool operator!=(TransformIterator const& other) const + { + return !this->operator==(other); + } + + auto operator*() const + -> decltype(std::declval()(*std::declval())) + { + return this->Func(*this->Base); + } + +private: + Iter Base; + UnaryFunction Func; +}; + +} // namespace RangeIterators + template class cmRange { @@ -74,6 +190,22 @@ public: return std::none_of(this->Begin, this->End, std::ref(p)); } + template + auto filter(UnaryPredicate p) const + -> cmRange> + { + using It = RangeIterators::FilterIterator; + return { It(this->Begin, this->End, p), It(this->End, this->End, p) }; + } + + template + auto transform(UnaryFunction f) const + -> cmRange> + { + using It = RangeIterators::TransformIterator; + return { It(this->Begin, f), It(this->End, f) }; + } + private: Iter Begin; Iter End; -- cgit v0.12