1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-17 15:32:10 +08:00

cmRange: Add functions filter and transform

This commit is contained in:
Regina Pfeifer
2019-02-15 21:54:58 +01:00
committed by Brad King
parent da4773e8b8
commit a8d51ef8b7

View File

@@ -9,6 +9,122 @@
#include <functional>
#include <iterator>
namespace RangeIterators {
template <typename Iter, typename UnaryPredicate>
class FilterIterator
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = typename std::iterator_traits<Iter>::value_type;
using difference_type = typename std::iterator_traits<Iter>::difference_type;
using pointer = typename std::iterator_traits<Iter>::pointer;
using reference = typename std::iterator_traits<Iter>::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<Iter>())
{
return *this->Cur;
}
private:
void SatisfyPredicate()
{
while (this->Cur != this->End && !this->Pred(*this->Cur)) {
++this->Cur;
}
}
Iter Cur;
Iter End;
UnaryPredicate Pred;
};
template <typename Iter, typename UnaryFunction>
class TransformIterator
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type =
typename std::remove_cv<typename std::remove_reference<decltype(
std::declval<UnaryFunction>()(*std::declval<Iter>()))>::type>::type;
using difference_type = typename std::iterator_traits<Iter>::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<UnaryFunction>()(*std::declval<Iter>()))
{
return this->Func(*this->Base);
}
private:
Iter Base;
UnaryFunction Func;
};
} // namespace RangeIterators
template <typename Iter>
class cmRange
{
@@ -74,6 +190,22 @@ public:
return std::none_of(this->Begin, this->End, std::ref(p));
}
template <typename UnaryPredicate>
auto filter(UnaryPredicate p) const
-> cmRange<RangeIterators::FilterIterator<Iter, UnaryPredicate>>
{
using It = RangeIterators::FilterIterator<Iter, UnaryPredicate>;
return { It(this->Begin, this->End, p), It(this->End, this->End, p) };
}
template <typename UnaryFunction>
auto transform(UnaryFunction f) const
-> cmRange<RangeIterators::TransformIterator<Iter, UnaryFunction>>
{
using It = RangeIterators::TransformIterator<Iter, UnaryFunction>;
return { It(this->Begin, f), It(this->End, f) };
}
private:
Iter Begin;
Iter End;