You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

95 lines
2.1 KiB

/**
* Copyright (c) 2018 Niklas Rosenstein
* MIT licensed.
*
* @description Provides a #filter() iterator.
*/
#pragma once
#include <functional>
#include "iterator.hpp"
namespace niklasrosenstein {
/**
* The actual iterator behind #filter().
*/
template <class T>
class _filter : public iterator<_filter<T>> {
public:
using iterator_type = decltype(std::declval<T>().begin());
using value_type = decltype(std::declval<iterator_type>().operator*());
using filter_type = std::function<bool(value_type)>;
private:
T _iter;
filter_type _func;
iterator_type _curr;
iterator_type const _end;
public:
inline _filter(T&& iter, filter_type&& func)
: _iter(std::move(iter)),
_func(std::move(func)),
_curr(_iter.begin()),
_end(_iter.end())
{}
typedef value_type yield_type;
inline bool has_next() {
// Consume the initial elements that should be filtered out.
while (_curr != _end && !_func(*_curr)) {
++_curr;
}
return _curr != _end;
}
inline void next() {
while (_curr != _end) {
++_curr;
if (_curr != _end && _func(*_curr)) {
break;
}
}
}
inline value_type operator * () const {
return *_curr;
}
};
/**
* Filters items which do not evaluate to #true when casting to #bool.
* @{
*/
template <class T>
inline _filter<T> filter(T&& iter) {
using VT = typename _filter<T>::value_type;
return filter(std::move(iter), [](VT v) { return (bool) v; });
}
template <class T>
inline _filter<movable_iterator_wrapper<T>> filter(T& iter) {
return filter(movable_iterator_wrapper<T>(iter));
}
// @}
/**
* Filters out items for which the callable #func returns false.
* @{
*/
template <class T, class F>
inline _filter<T> filter(T&& iter, F&& func) {
return {(std::move(iter)), func};
}
template <class T, class F>
inline _filter<movable_iterator_wrapper<T>> filter(T& iter, F&& func) {
return filter(movable_iterator_wrapper<T>(iter), func);
}
// @}
} // namespace niklasrosenstein