forked from OctaForge/libostd
add IteratorRange to make a range out of any two iterators
This commit is contained in:
parent
62b0c2ecf7
commit
6ec72a6ecd
153
ostd/range.hh
153
ostd/range.hh
|
@ -12,6 +12,7 @@
|
|||
#include <new>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
#include "ostd/types.hh"
|
||||
#include "ostd/utility.hh"
|
||||
|
@ -1754,6 +1755,158 @@ inline AppenderRange<T> appender(T &&v) {
|
|||
return AppenderRange<T>(std::forward<T>(v));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename>
|
||||
struct IteratorRangeTagBase {
|
||||
/* fallback, the most basic range */
|
||||
using Type = InputRangeTag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct IteratorRangeTagBase<std::output_iterator_tag> {
|
||||
using Type = OutputRangeTag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct IteratorRangeTagBase<std::forward_iterator_tag> {
|
||||
using Type = ForwardRangeTag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct IteratorRangeTagBase<std::bidirectional_iterator_tag> {
|
||||
using Type = BidirectionalRangeTag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct IteratorRangeTagBase<std::random_access_iterator_tag> {
|
||||
using Type = FiniteRandomAccessRangeTag;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using IteratorRangeTag = typename detail::IteratorRangeTagBase<T>::Type;
|
||||
|
||||
template<typename T>
|
||||
struct IteratorRange: InputRange<
|
||||
IteratorRange<T>,
|
||||
IteratorRangeTag<typename std::iterator_traits<T>::iterator_category>,
|
||||
typename std::iterator_traits<T>::value_type,
|
||||
typename std::iterator_traits<T>::reference,
|
||||
size_t,
|
||||
typename std::iterator_traits<T>::difference_type
|
||||
> {
|
||||
private:
|
||||
struct Nat {};
|
||||
|
||||
using RefT = typename std::iterator_traits<T>::reference;
|
||||
using DiffT = typename std::iterator_traits<T>::difference_type;
|
||||
|
||||
public:
|
||||
IteratorRange(T beg = T{}, T end = T{}): p_beg(beg), p_end(end) {}
|
||||
IteratorRange(T beg, size_t n): p_beg(beg), p_end(beg + n) {}
|
||||
|
||||
IteratorRange(IteratorRange const &v): p_beg(v.p_beg), p_end(v.p_end) {}
|
||||
IteratorRange(IteratorRange &&v):
|
||||
p_beg(std::move(v.p_beg)), p_end(std::move(v.p_end))
|
||||
{}
|
||||
|
||||
IteratorRange &operator=(IteratorRange const &v) {
|
||||
p_beg = v.p_beg;
|
||||
p_end = v.p_end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
IteratorRange &operator=(IteratorRange &&v) {
|
||||
p_beg = std::move(v.p_beg);
|
||||
p_end = std::move(v.p_end);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* satisfy InputRange / ForwardRange */
|
||||
bool empty() const { return p_beg == p_end; }
|
||||
|
||||
bool pop_front() {
|
||||
if (p_beg == p_end) {
|
||||
return false;
|
||||
}
|
||||
++p_beg;
|
||||
return true;
|
||||
}
|
||||
bool push_front() {
|
||||
--p_beg; return true;
|
||||
}
|
||||
|
||||
RefT front() const { return *p_beg; }
|
||||
|
||||
bool equals_front(IteratorRange const &range) const {
|
||||
return p_beg == range.p_beg;
|
||||
}
|
||||
|
||||
DiffT distance_front(IteratorRange const &range) const {
|
||||
return range.p_beg - p_beg;
|
||||
}
|
||||
|
||||
/* satisfy BidirectionalRange */
|
||||
bool pop_back() {
|
||||
if (p_end == p_beg) {
|
||||
return false;
|
||||
}
|
||||
--p_end;
|
||||
return true;
|
||||
}
|
||||
bool push_back() {
|
||||
++p_end; return true;
|
||||
}
|
||||
|
||||
RefT back() const { return *(p_end - 1); }
|
||||
|
||||
bool equals_back(IteratorRange const &range) const {
|
||||
return p_end == range.p_end;
|
||||
}
|
||||
|
||||
ptrdiff_t distance_back(IteratorRange const &range) const {
|
||||
return range.p_end - p_end;
|
||||
}
|
||||
|
||||
/* satisfy FiniteRandomAccessRange */
|
||||
size_t size() const { return p_end - p_beg; }
|
||||
|
||||
IteratorRange slice(size_t start, size_t end) const {
|
||||
return IteratorRange(p_beg + start, p_beg + end);
|
||||
}
|
||||
|
||||
RefT operator[](size_t i) const { return p_beg[i]; }
|
||||
|
||||
/* satisfy OutputRange */
|
||||
bool put(T const &v) {
|
||||
if (empty()) {
|
||||
return false;
|
||||
}
|
||||
*(p_beg++) = v;
|
||||
return true;
|
||||
}
|
||||
bool put(T &&v) {
|
||||
if (empty()) {
|
||||
return false;
|
||||
}
|
||||
*(p_beg++) = std::move(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
T p_beg, p_end;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
IteratorRange<T> make_range(T beg, T end) {
|
||||
return IteratorRange<T>{beg, end};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IteratorRange<T> make_range(T beg, size_t n) {
|
||||
return IteratorRange<T>{beg, beg + n};
|
||||
}
|
||||
|
||||
} /* namespace ostd */
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue