remove the range half stuff for now
parent
9d08f4361d
commit
6ddb0f1b17
|
@ -132,7 +132,7 @@ From forward ranges onwards, independence of state is guaranteed though.
|
|||
|
||||
This method checks whether the range has any elements left in it. If this
|
||||
returns true, it means `front()` is safe to use. Safe code should always
|
||||
check; the behavior is an item is retrieved on an empty range.
|
||||
check; the behavior is undefined if an item is retrieved on an empty range.
|
||||
|
||||
~~~{.cc}
|
||||
bool equals_front() const;
|
||||
|
|
317
ostd/range.hh
317
ostd/range.hh
|
@ -250,227 +250,6 @@ namespace detail {
|
|||
};
|
||||
}
|
||||
|
||||
// range half
|
||||
|
||||
template<typename T>
|
||||
struct half_range;
|
||||
|
||||
namespace detail {
|
||||
template<typename R, bool = is_bidirectional_range<typename R::range>>
|
||||
struct range_add;
|
||||
|
||||
template<typename R>
|
||||
struct range_add<R, true> {
|
||||
using diff_t = range_difference_t<typename R::range>;
|
||||
|
||||
static diff_t add_n(R &half, diff_t n) {
|
||||
if (n < 0) {
|
||||
return -half.prev_n(n);
|
||||
}
|
||||
return half.next_n(n);
|
||||
}
|
||||
static diff_t sub_n(R &half, diff_t n) {
|
||||
if (n < 0) {
|
||||
return -half.next_n(n);
|
||||
}
|
||||
return half.prev_n(n);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
struct range_add<R, false> {
|
||||
using diff_t = range_difference_t<typename R::range>;
|
||||
|
||||
static diff_t add_n(R &half, diff_t n) {
|
||||
if (n < 0) {
|
||||
return 0;
|
||||
}
|
||||
return half.next_n(n);
|
||||
}
|
||||
static diff_t sub_n(R &half, diff_t n) {
|
||||
if (n < 0) {
|
||||
return 0;
|
||||
}
|
||||
return half.prev_n(n);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename>
|
||||
struct range_iterator_tag {
|
||||
/* better range types all become random access iterators */
|
||||
using type = std::random_access_iterator_tag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct range_iterator_tag<input_range_tag> {
|
||||
using type = std::input_iterator_tag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct range_iterator_tag<output_range_tag> {
|
||||
using type = std::output_iterator_tag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct range_iterator_tag<forward_range_tag> {
|
||||
using type = std::forward_iterator_tag;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct range_iterator_tag<bidirectional_range_tag> {
|
||||
using type = std::bidirectional_iterator_tag;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct range_half {
|
||||
private:
|
||||
T p_range;
|
||||
public:
|
||||
using range = T;
|
||||
|
||||
using iterator_category = typename detail::range_iterator_tag<T>::type;
|
||||
using value_type = range_value_t<T>;
|
||||
using difference_type = range_difference_t<T>;
|
||||
using pointer = range_value_t<T> *;
|
||||
using reference = range_reference_t<T>;
|
||||
|
||||
range_half() = delete;
|
||||
range_half(T const &range): p_range(range) {}
|
||||
|
||||
template<typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
|
||||
range_half(range_half<U> const &half): p_range(half.p_range) {}
|
||||
|
||||
range_half(range_half const &half): p_range(half.p_range) {}
|
||||
range_half(range_half &&half): p_range(std::move(half.p_range)) {}
|
||||
|
||||
range_half &operator=(range_half const &half) {
|
||||
p_range = half.p_range;
|
||||
return *this;
|
||||
}
|
||||
|
||||
range_half &operator=(range_half &&half) {
|
||||
p_range = std::move(half.p_range);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void next() { p_range.pop_front(); }
|
||||
void prev() { p_range.push_front(); }
|
||||
|
||||
void next_n(range_size_t<T> n) {
|
||||
p_range.pop_front_n(n);
|
||||
}
|
||||
void prev_n(range_size_t<T> n) {
|
||||
p_range.push_front_n(n);
|
||||
}
|
||||
|
||||
range_difference_t<T> add_n(range_difference_t<T> n) {
|
||||
return detail::range_add<range_half<T>>::add_n(*this, n);
|
||||
}
|
||||
range_difference_t<T> sub_n(range_difference_t<T> n) {
|
||||
return detail::range_add<range_half<T>>::sub_n(*this, n);
|
||||
}
|
||||
|
||||
range_reference_t<T> get() const {
|
||||
return p_range.front();
|
||||
}
|
||||
|
||||
range_difference_t<T> distance(range_half const &half) const {
|
||||
return p_range.distance_front(half.p_range);
|
||||
}
|
||||
|
||||
bool equals(range_half const &half) const {
|
||||
return p_range.equals_front(half.p_range);
|
||||
}
|
||||
|
||||
bool operator==(range_half const &half) const {
|
||||
return equals(half);
|
||||
}
|
||||
bool operator!=(range_half const &half) const {
|
||||
return !equals(half);
|
||||
}
|
||||
bool operator<(range_half const &half) const {
|
||||
return distance(half) > 0;
|
||||
}
|
||||
bool operator>(range_half const &half) const {
|
||||
return distance(half) < 0;
|
||||
}
|
||||
bool operator<=(range_half const &half) const {
|
||||
return distance(half) >= 0;
|
||||
}
|
||||
bool operator>=(range_half const &half) const {
|
||||
return distance(half) <= 0;
|
||||
}
|
||||
|
||||
/* iterator like interface */
|
||||
|
||||
range_reference_t<T> operator*() const {
|
||||
return p_range.front();
|
||||
}
|
||||
|
||||
range_reference_t<T> operator[](range_size_t<T> idx) const {
|
||||
return p_range[idx];
|
||||
}
|
||||
|
||||
range_half &operator++() {
|
||||
next();
|
||||
return *this;
|
||||
}
|
||||
range_half operator++(int) {
|
||||
range_half tmp(*this);
|
||||
next();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
range_half &operator--() {
|
||||
prev();
|
||||
return *this;
|
||||
}
|
||||
range_half operator--(int) {
|
||||
range_half tmp(*this);
|
||||
prev();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
range_half operator+(range_difference_t<T> n) const {
|
||||
range_half tmp(*this);
|
||||
tmp.add_n(n);
|
||||
return tmp;
|
||||
}
|
||||
range_half operator-(range_difference_t<T> n) const {
|
||||
range_half tmp(*this);
|
||||
tmp.sub_n(n);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
range_half &operator+=(range_difference_t<T> n) {
|
||||
add_n(n);
|
||||
return *this;
|
||||
}
|
||||
range_half &operator-=(range_difference_t<T> n) {
|
||||
sub_n(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T iter() const { return p_range; }
|
||||
|
||||
half_range<range_half> iter(range_half const &other) const {
|
||||
return half_range<range_half>(*this, other);
|
||||
}
|
||||
|
||||
range_value_t<T> *data() { return p_range.data(); }
|
||||
range_value_t<T> const *data() const { return p_range.data(); }
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
inline range_difference_t<R> operator-(
|
||||
range_half<R> const &lhs, range_half<R> const &rhs
|
||||
) {
|
||||
return rhs.distance(lhs);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename R>
|
||||
void pop_front_n(R &range, range_size_t<R> n) {
|
||||
|
@ -581,10 +360,6 @@ struct input_range {
|
|||
return zip_range<B, R1, RR...>(iter(), std::move(r1), std::move(rr)...);
|
||||
}
|
||||
|
||||
range_half<B> half() const {
|
||||
return range_half<B>(iter());
|
||||
}
|
||||
|
||||
/* iterator like interface operating on the front part of the range
|
||||
* this is sometimes convenient as it can be used within expressions */
|
||||
|
||||
|
@ -851,98 +626,6 @@ namespace detail {
|
|||
constexpr bool iterable_test = decltype(test_iterable<T>(0))::value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct half_range: input_range<half_range<T>> {
|
||||
using range_category = range_category_t <typename T::range>;
|
||||
using value_type = range_value_t <typename T::range>;
|
||||
using reference = range_reference_t <typename T::range>;
|
||||
using size_type = range_size_t <typename T::range>;
|
||||
using difference_type = range_difference_t<typename T::range>;
|
||||
|
||||
private:
|
||||
T p_beg;
|
||||
T p_end;
|
||||
|
||||
public:
|
||||
half_range() = delete;
|
||||
half_range(half_range const &range):
|
||||
p_beg(range.p_beg), p_end(range.p_end)
|
||||
{}
|
||||
half_range(half_range &&range):
|
||||
p_beg(std::move(range.p_beg)), p_end(std::move(range.p_end))
|
||||
{}
|
||||
half_range(T const &beg, T const &end):
|
||||
p_beg(beg),p_end(end)
|
||||
{}
|
||||
half_range(T &&beg, T &&end):
|
||||
p_beg(std::move(beg)), p_end(std::move(end))
|
||||
{}
|
||||
|
||||
half_range &operator=(half_range const &range) {
|
||||
p_beg = range.p_beg;
|
||||
p_end = range.p_end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
half_range &operator=(half_range &&range) {
|
||||
p_beg = std::move(range.p_beg);
|
||||
p_end = std::move(range.p_end);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return p_beg == p_end; }
|
||||
|
||||
void pop_front() {
|
||||
p_beg.next();
|
||||
}
|
||||
void push_front() {
|
||||
p_beg.prev();
|
||||
}
|
||||
void pop_back() {
|
||||
p_end.prev();
|
||||
}
|
||||
void push_back() {
|
||||
p_end.next();
|
||||
}
|
||||
|
||||
reference front() const { return *p_beg; }
|
||||
reference back() const { return *(p_end - 1); }
|
||||
|
||||
bool equals_front(half_range const &range) const {
|
||||
return p_beg == range.p_beg;
|
||||
}
|
||||
bool equals_back(half_range const &range) const {
|
||||
return p_end == range.p_end;
|
||||
}
|
||||
|
||||
difference_type distance_front(half_range const &range) const {
|
||||
return range.p_beg - p_beg;
|
||||
}
|
||||
difference_type distance_back(half_range const &range) const {
|
||||
return range.p_end - p_end;
|
||||
}
|
||||
|
||||
size_type size() const { return p_end - p_beg; }
|
||||
|
||||
half_range slice(size_type start, size_type end) const {
|
||||
return half_range{p_beg + start, p_beg + end};
|
||||
}
|
||||
|
||||
reference operator[](size_type idx) const {
|
||||
return p_beg[idx];
|
||||
}
|
||||
|
||||
void put(value_type const &v) {
|
||||
p_beg.range().put(v);
|
||||
}
|
||||
void put(value_type &&v) {
|
||||
p_beg.range().put(std::move(v));
|
||||
}
|
||||
|
||||
value_type *data() { return p_beg.data(); }
|
||||
value_type const *data() const { return p_beg.data(); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct reverse_range: input_range<reverse_range<T>> {
|
||||
using range_category = std::common_type_t<
|
||||
|
|
Loading…
Reference in New Issue