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
|
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
|
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}
|
~~~{.cc}
|
||||||
bool equals_front() const;
|
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 {
|
namespace detail {
|
||||||
template<typename R>
|
template<typename R>
|
||||||
void pop_front_n(R &range, range_size_t<R> n) {
|
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)...);
|
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
|
/* iterator like interface operating on the front part of the range
|
||||||
* this is sometimes convenient as it can be used within expressions */
|
* 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;
|
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>
|
template<typename T>
|
||||||
struct reverse_range: input_range<reverse_range<T>> {
|
struct reverse_range: input_range<reverse_range<T>> {
|
||||||
using range_category = std::common_type_t<
|
using range_category = std::common_type_t<
|
||||||
|
|
Loading…
Reference in New Issue