diff --git a/octa/range.h b/octa/range.h index eb76979..65fae35 100644 --- a/octa/range.h +++ b/octa/range.h @@ -13,944 +13,954 @@ #include "octa/type_traits.h" namespace octa { - struct InputRangeTag {}; - struct OutputRangeTag {}; - struct ForwardRangeTag: InputRangeTag {}; - struct BidirectionalRangeTag: ForwardRangeTag {}; - struct RandomAccessRangeTag: BidirectionalRangeTag {}; - struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {}; - template struct RangeHalf; +struct InputRangeTag {}; +struct OutputRangeTag {}; +struct ForwardRangeTag: InputRangeTag {}; +struct BidirectionalRangeTag: ForwardRangeTag {}; +struct RandomAccessRangeTag: BidirectionalRangeTag {}; +struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {}; -#define __OCTA_RANGE_TRAIT(_Name, _TypeName) \ +template struct RangeHalf; + +#define OCTA_RANGE_TRAIT(_Name, _TypeName) \ +namespace detail { \ template \ - struct __OctaRange##_Name { \ + struct Range##_Name##Base { \ typedef typename _T::_TypeName Type; \ }; \ template \ - struct __OctaRange##_Name> { \ + struct Range##_Name##Base> { \ typedef typename _T::_TypeName Type; \ }; \ - template \ - using Range##_Name = typename __OctaRange##_Name<_T>::Type; +} \ +template \ +using Range##_Name = typename octa::detail::Range##_Name##Base<_T>::Type; - __OCTA_RANGE_TRAIT(Category, Category) - __OCTA_RANGE_TRAIT(Size, Size) - __OCTA_RANGE_TRAIT(Value, Value) - __OCTA_RANGE_TRAIT(Reference, Reference) - __OCTA_RANGE_TRAIT(Difference, Difference) +OCTA_RANGE_TRAIT(Category, Category) +OCTA_RANGE_TRAIT(Size, Size) +OCTA_RANGE_TRAIT(Value, Value) +OCTA_RANGE_TRAIT(Reference, Reference) +OCTA_RANGE_TRAIT(Difference, Difference) -#undef __OCTA_RANGE_TRAIT +#undef OCTA_RANGE_TRAIT - // is input range +// is input range - template, InputRangeTag - >::value> struct IsInputRange: False {}; +template, InputRangeTag +>::value> struct IsInputRange: False {}; - template - struct IsInputRange<_T, true>: True {}; +template +struct IsInputRange<_T, true>: True {}; - // is forward range +// is forward range - template, ForwardRangeTag - >::value> struct IsForwardRange: False {}; +template, ForwardRangeTag +>::value> struct IsForwardRange: False {}; - template - struct IsForwardRange<_T, true>: True {}; +template +struct IsForwardRange<_T, true>: True {}; - // is bidirectional range +// is bidirectional range - template, BidirectionalRangeTag - >::value> struct IsBidirectionalRange: False {}; +template, BidirectionalRangeTag +>::value> struct IsBidirectionalRange: False {}; - template - struct IsBidirectionalRange<_T, true>: True {}; +template +struct IsBidirectionalRange<_T, true>: True {}; - // is random access range +// is random access range - template, RandomAccessRangeTag - >::value> struct IsRandomAccessRange: False {}; +template, RandomAccessRangeTag +>::value> struct IsRandomAccessRange: False {}; - template - struct IsRandomAccessRange<_T, true>: True {}; +template +struct IsRandomAccessRange<_T, true>: True {}; - // is finite random access range +// is finite random access range - template, FiniteRandomAccessRangeTag - >::value> struct IsFiniteRandomAccessRange: False {}; +template, FiniteRandomAccessRangeTag +>::value> struct IsFiniteRandomAccessRange: False {}; - template - struct IsFiniteRandomAccessRange<_T, true>: True {}; +template +struct IsFiniteRandomAccessRange<_T, true>: True {}; - // is infinite random access range +// is infinite random access range - template - struct IsInfiniteRandomAccessRange: IntegralConstant::value && !IsFiniteRandomAccessRange<_T>::value) - > {}; +template +struct IsInfiniteRandomAccessRange: IntegralConstant::value && !IsFiniteRandomAccessRange<_T>::value) +> {}; - // is output range +// is output range +namespace detail { template - struct __OctaOutputRangeTest { - template struct __Test {}; - template static char __test(__Test<_U, &_U::put> *); - template static int __test(...); - static constexpr bool value = (sizeof(__test<_T>(0)) == sizeof(char)); + struct OutputRangeTest { + template struct Test {}; + template static char test(Test<_U, &_U::put> *); + template static int test(...); + static constexpr bool value = (sizeof(test<_T>(0)) == sizeof(char)); }; +} - template, OutputRangeTag - >::value || (IsInputRange<_T>::value && - (__OctaOutputRangeTest<_T, const RangeValue<_T> &>::value || - __OctaOutputRangeTest<_T, RangeValue<_T> &&>::value) - ))> struct IsOutputRange: False {}; +template, OutputRangeTag +>::value || (IsInputRange<_T>::value && + (octa::detail::OutputRangeTest<_T, const RangeValue<_T> &>::value || + octa::detail::OutputRangeTest<_T, RangeValue<_T> &&>::value) +))> struct IsOutputRange: False {}; - template - struct IsOutputRange<_T, true>: True {}; +template +struct IsOutputRange<_T, true>: True {}; +namespace detail { // range iterator template - struct __OctaRangeIterator { - __OctaRangeIterator(): __range() {} - explicit __OctaRangeIterator(const _T &__range): __range(__range) {} - __OctaRangeIterator &operator++() { - __range.pop_front(); + struct RangeIterator { + RangeIterator(): p_range() {} + explicit RangeIterator(const _T &range): p_range(range) {} + RangeIterator &operator++() { + p_range.pop_front(); return *this; } RangeReference<_T> operator*() const { - return __range.front(); + return p_range.front(); } - bool operator!=(__OctaRangeIterator) const { return !__range.empty(); } + bool operator!=(RangeIterator) const { return !p_range.empty(); } private: - _T __range; + _T p_range; }; +} - // range half +// range half - template - struct RangeHalf { - private: - _T __range; - public: - typedef _T Range; +template +struct RangeHalf { +private: + _T p_range; +public: + typedef _T Range; - RangeHalf(): __range() {} - RangeHalf(const _T &__range): __range(__range) {} - RangeHalf(const RangeHalf &__half): __range(__half.__range) {} - RangeHalf(RangeHalf &&__half): __range(octa::move(__half.__range)) {} + RangeHalf(): p_range() {} + RangeHalf(const _T &range): p_range(range) {} + RangeHalf(const RangeHalf &half): p_range(half.p_range) {} + RangeHalf(RangeHalf &&half): p_range(octa::move(half.p_range)) {} - RangeHalf &operator=(const RangeHalf &__half) { - __range = __half.__range; - return *this; - } + RangeHalf &operator=(const RangeHalf &half) { + p_range = half.p_range; + return *this; + } - RangeHalf &operator=(RangeHalf &&__half) { - __range = octa::move(__half.__range); - return *this; - } + RangeHalf &operator=(RangeHalf &&half) { + p_range = octa::move(half.p_range); + return *this; + } - _T range() const { return __range; } + _T range() const { return p_range; } - bool next() { return __range.pop_front(); } - bool prev() { return __range.push_front(); } + bool next() { return p_range.pop_front(); } + bool prev() { return p_range.push_front(); } - RangeSize<_T> next_n(RangeSize<_T> __n) { - return __range.pop_front_n(__n); - } - RangeSize<_T> prev_n(RangeSize<_T> __n) { - return __range.push_front_n(__n); - } + RangeSize<_T> next_n(RangeSize<_T> n) { + return p_range.pop_front_n(n); + } + RangeSize<_T> prev_n(RangeSize<_T> n) { + return p_range.push_front_n(n); + } - RangeReference<_T> get() const { - return __range.front(); - } + RangeReference<_T> get() const { + return p_range.front(); + } - RangeDifference<_T> distance(const RangeHalf &__half) const { - return __range.distance_front(__half.__range); - } + RangeDifference<_T> distance(const RangeHalf &half) const { + return p_range.distance_front(half.p_range); + } - bool equals(const RangeHalf &__half) const { - return __range.equals_front(__half.__range); - } + bool equals(const RangeHalf &half) const { + return p_range.equals_front(half.p_range); + } - bool operator==(const RangeHalf &__half) const { - return equals(__half); - } - bool operator!=(const RangeHalf &__half) const { - return !equals(__half); - } + bool operator==(const RangeHalf &half) const { + return equals(half); + } + bool operator!=(const RangeHalf &half) const { + return !equals(half); + } - /* iterator like interface */ + /* iterator like interface */ - RangeReference<_T> operator*() const { - return get(); - } + RangeReference<_T> operator*() const { + return get(); + } - RangeReference<_T> operator[](RangeSize<_T> __idx) const { - return __range[__idx]; - } + RangeReference<_T> operator[](RangeSize<_T> idx) const { + return p_range[idx]; + } - RangeHalf &operator++() { - next(); - return *this; - } - RangeHalf operator++(int) { - RangeHalf __tmp(*this); - next(); - return octa::move(__tmp); - } + RangeHalf &operator++() { + next(); + return *this; + } + RangeHalf operator++(int) { + RangeHalf tmp(*this); + next(); + return octa::move(tmp); + } - RangeHalf &operator--() { - prev(); - return *this; - } - RangeHalf operator--(int) { - RangeHalf __tmp(*this); - prev(); - return octa::move(__tmp); - } + RangeHalf &operator--() { + prev(); + return *this; + } + RangeHalf operator--(int) { + RangeHalf tmp(*this); + prev(); + return octa::move(tmp); + } - RangeHalf operator+(RangeDifference<_T> __n) { - RangeHalf __tmp(*this); - if (__n < 0) __tmp.prev_n(-__n); - else __tmp.next_n(__n); - return octa::move(__tmp); - } - RangeHalf operator-(RangeDifference<_T> __n) { - RangeHalf __tmp(*this); - if (__n < 0) __tmp.next_n(-__n); - else __tmp.prev_n(__n); - return octa::move(__tmp); - } + RangeHalf operator+(RangeDifference<_T> n) { + RangeHalf tmp(*this); + if (n < 0) tmp.prev_n(-n); + else tmp.next_n(n); + return octa::move(tmp); + } + RangeHalf operator-(RangeDifference<_T> n) { + RangeHalf tmp(*this); + if (n < 0) tmp.next_n(-n); + else tmp.prev_n(n); + return octa::move(tmp); + } - RangeHalf &operator+=(RangeDifference<_T> __n) { - if (__n < 0) prev_n(-__n); - else next_n(__n); - return *this; - } - RangeHalf &operator-=(RangeDifference<_T> __n) { - if (__n < 0) next_n(-__n); - else prev_n(__n); - return *this; - } - }; + RangeHalf &operator+=(RangeDifference<_T> n) { + if (n < 0) prev_n(-n); + else next_n(n); + return *this; + } + RangeHalf &operator-=(RangeDifference<_T> n) { + if (n < 0) next_n(-n); + else prev_n(n); + return *this; + } +}; +template +RangeDifference<_R> operator-(const _R &lhs, const _R &rhs) { + return rhs.distance(lhs); +} + +namespace detail { template - RangeDifference<_R> operator-(const _R &__lhs, const _R &__rhs) { - return __rhs.distance(__lhs); + RangeSize<_R> pop_front_n(_R &range, RangeSize<_R> n) { + for (RangeSize<_R> i = 0; i < n; ++i) + if (!range.pop_front()) return i; + return n; } template - RangeSize<_R> __octa_pop_front_n(_R &__range, RangeSize<_R> __n) { - for (RangeSize<_R> __i = 0; __i < __n; ++__i) - if (!__range.pop_front()) return __i; - return __n; + RangeSize<_R> pop_back_n(_R &range, RangeSize<_R> n) { + for (RangeSize<_R> i = 0; i < n; ++i) + if (!range.pop_back()) return i; + return n; } template - RangeSize<_R> __octa_pop_back_n(_R &__range, RangeSize<_R> __n) { - for (RangeSize<_R> __i = 0; __i < __n; ++__i) - if (!__range.pop_back()) return __i; - return __n; + RangeSize<_R> push_front_n(_R &range, RangeSize<_R> n) { + for (RangeSize<_R> i = 0; i < n; ++i) + if (!range.push_front()) return i; + return n; } template - RangeSize<_R> __octa_push_front_n(_R &__range, RangeSize<_R> __n) { - for (RangeSize<_R> __i = 0; __i < __n; ++__i) - if (!__range.push_front()) return __i; - return __n; - } - - template - RangeSize<_R> __octa_push_back_n(_R &__range, RangeSize<_R> __n) { - for (RangeSize<_R> __i = 0; __i < __n; ++__i) - if (!__range.push_back()) return __i; - return __n; - } - - template struct InputRange { - typedef _C Category; - typedef _S Size; - typedef _D Difference; - typedef _V Value; - typedef _R Reference; - - __OctaRangeIterator<_B> begin() const { - return __OctaRangeIterator<_B>((const _B &)*this); - } - __OctaRangeIterator<_B> end() const { - return __OctaRangeIterator<_B>(); - } - - Size pop_front_n(Size __n) { - return __octa_pop_front_n<_B>(*((_B *)this), __n); - } - - Size pop_back_n(Size __n) { - return __octa_pop_back_n<_B>(*((_B *)this), __n); - } - - Size push_front_n(Size __n) { - return __octa_push_front_n<_B>(*((_B *)this), __n); - } - - Size push_back_n(Size __n) { - return __octa_push_back_n<_B>(*((_B *)this), __n); - } - - _B each() const { - return _B(*((_B *)this)); - } - - RangeHalf<_B> half() const { - return RangeHalf<_B>(*((_B *)this)); - } - }; - - template struct OutputRange { - typedef OutputRangeTag Category; - typedef _S Size; - typedef _D Difference; - typedef _V Value; - typedef _R Reference; - }; - - template - struct ReverseRange: InputRange, - RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>, - RangeDifference<_T> - > { - private: - typedef RangeReference<_T> _r_ref; - typedef RangeSize<_T> _r_size; - - _T __range; - - public: - ReverseRange(): __range() {} - - ReverseRange(const _T &__range): __range(__range) {} - - ReverseRange(const ReverseRange &__it): __range(__it.__range) {} - - ReverseRange(ReverseRange &&__it): __range(octa::move(__it.__range)) {} - - ReverseRange &operator=(const ReverseRange &__v) { - __range = __v.__range; - return *this; - } - ReverseRange &operator=(ReverseRange &&__v) { - __range = octa::move(__v.__range); - return *this; - } - ReverseRange &operator=(const _T &__v) { - __range = __v; - return *this; - } - ReverseRange &operator=(_T &&__v) { - __range = octa::move(__v); - return *this; - } - - bool empty() const { return __range.empty(); } - _r_size size() const { return __range.size(); } - - bool equals_front(const ReverseRange &__r) const { - return __range.equals_back(__r.__range); - } - bool equals_back(const ReverseRange &__r) const { - return __range.equals_front(__r.__range); - } - - RangeDifference<_T> distance_front(const ReverseRange &__r) const { - return -__range.distance_back(__r.__range); - } - RangeDifference<_T> distance_back(const ReverseRange &__r) const { - return -__range.distance_front(__r.__range); - } - - bool pop_front() { return __range.pop_back(); } - bool pop_back() { return __range.pop_front(); } - - bool push_front() { return __range.push_back(); } - bool push_back() { return __range.push_front(); } - - _r_size pop_front_n(_r_size __n) { return __range.pop_front_n(__n); } - _r_size pop_back_n(_r_size __n) { return __range.pop_back_n(__n); } - - _r_size push_front_n(_r_size __n) { return __range.push_front_n(__n); } - _r_size push_back_n(_r_size __n) { return __range.push_back_n(__n); } - - _r_ref front() const { return __range.back(); } - _r_ref back() const { return __range.front(); } - - _r_ref operator[](_r_size __i) const { return __range[size() - __i - 1]; } - - ReverseRange<_T> slice(_r_size __start, _r_size __end) const { - _r_size __len = __range.size(); - return ReverseRange<_T>(__range.slice(__len - __end, __len - __start)); - } - }; - - template - ReverseRange<_T> make_reverse_range(const _T &__it) { - return ReverseRange<_T>(__it); - } - - template - struct MoveRange: InputRange, - RangeCategory<_T>, RangeValue<_T>, RangeValue<_T> &&, RangeSize<_T>, - RangeDifference<_T> - > { - private: - typedef RangeValue<_T> _r_val; - typedef RangeValue<_T> &&_r_ref; - typedef RangeSize<_T> _r_size; - - _T __range; - - public: - MoveRange(): __range() {} - - MoveRange(const _T &__range): __range(__range) {} - - MoveRange(const MoveRange &__it): __range(__it.__range) {} - - MoveRange(MoveRange &&__it): __range(octa::move(__it.__range)) {} - - MoveRange &operator=(const MoveRange &__v) { - __range = __v.__range; - return *this; - } - MoveRange &operator=(MoveRange &&__v) { - __range = octa::move(__v.__range); - return *this; - } - MoveRange &operator=(const _T &__v) { - __range = __v; - return *this; - } - MoveRange &operator=(_T &&__v) { - __range = octa::move(__v); - return *this; - } - - bool empty() const { return __range.empty(); } - _r_size size() const { return __range.size(); } - - bool equals_front(const MoveRange &__r) const { - return __range.equals_front(__r.__range); - } - bool equals_back(const MoveRange &__r) const { - return __range.equals_back(__r.__range); - } - - RangeDifference<_T> distance_front(const MoveRange &__r) const { - return __range.distance_front(__r.__range); - } - RangeDifference<_T> distance_back(const MoveRange &__r) const { - return __range.distance_back(__r.__range); - } - - bool pop_front() { return __range.pop_front(); } - bool pop_back() { return __range.pop_back(); } - - bool push_front() { return __range.push_front(); } - bool push_back() { return __range.push_back(); } - - _r_size pop_front_n(_r_size __n) { return __range.pop_front_n(__n); } - _r_size pop_back_n(_r_size __n) { return __range.pop_back_n(__n); } - - _r_size push_front_n(_r_size __n) { return __range.push_front_n(__n); } - _r_size push_back_n(_r_size __n) { return __range.push_back_n(__n); } - - _r_ref front() const { return octa::move(__range.front()); } - _r_ref back() const { return octa::move(__range.back()); } - - _r_ref operator[](_r_size __i) const { return octa::move(__range[__i]); } - - MoveRange<_T> slice(_r_size __start, _r_size __end) const { - return MoveRange<_T>(__range.slice(__start, __end)); - } - - void put(const _r_val &__v) { __range.put(__v); } - void put(_r_val &&__v) { __range.put(octa::move(__v)); } - }; - - template - MoveRange<_T> make_move_range(const _T &__it) { - return MoveRange<_T>(__it); - } - - template - struct NumberRange: InputRange, ForwardRangeTag, _T, _T> { - NumberRange(): __a(0), __b(0), __step(0) {} - NumberRange(const NumberRange &__it): __a(__it.__a), __b(__it.__b), - __step(__it.__step) {} - NumberRange(_T __a, _T __b, _T __step = _T(1)): __a(__a), __b(__b), - __step(__step) {} - NumberRange(_T __v): __a(0), __b(__v), __step(1) {} - - bool empty() const { return __a * __step >= __b * __step; } - - bool equals_front(const NumberRange &__range) const { - return __a == __range.__a; - } - - bool pop_front() { __a += __step; return true; } - bool push_front() { __a -= __step; return true; } - _T front() const { return __a; } - - private: - _T __a, __b, __step; - }; - - template - NumberRange<_T> range(_T __a, _T __b, _T __step = _T(1)) { - return NumberRange<_T>(__a, __b, __step); - } - - template - NumberRange<_T> range(_T __v) { - return NumberRange<_T>(__v); - } - - template - struct PointerRange: InputRange, FiniteRandomAccessRangeTag, _T> { - PointerRange(): __beg(nullptr), __end(nullptr) {} - PointerRange(const PointerRange &__v): __beg(__v.__beg), - __end(__v.__end) {} - PointerRange(_T *__beg, _T *__end): __beg(__beg), __end(__end) {} - PointerRange(_T *__beg, size_t __n): __beg(__beg), __end(__beg + __n) {} - - PointerRange &operator=(const PointerRange &__v) { - __beg = __v.__beg; - __end = __v.__end; - return *this; - } - - /* satisfy InputRange / ForwardRange */ - bool empty() const { return __beg == __end; } - - bool pop_front() { - if (__beg == __end) return false; - ++__beg; - return true; - } - bool push_front() { - --__beg; return true; - } - - size_t pop_front_n(size_t __n) { - size_t __olen = __end - __beg; - __beg += __n; - if (__beg > __end) { - __beg = __end; - return __olen; - } - return __n; - } - - size_t push_front_n(size_t __n) { - __beg -= __n; return true; - } - - _T &front() const { return *__beg; } - - bool equals_front(const PointerRange &__range) const { - return __beg == __range.__beg; - } - - ptrdiff_t distance_front(const PointerRange &__range) const { - return __range.__beg - __beg; - } - - /* satisfy BidirectionalRange */ - bool pop_back() { - if (__end == __beg) return false; - --__end; - return true; - } - bool push_back() { - ++__end; return true; - } - - size_t pop_back_n(size_t __n) { - size_t __olen = __end - __beg; - __end -= __n; - if (__end < __beg) { - __end = __beg; - return __olen; - } - return __n; - } - - size_t push_back_n(size_t __n) { - __end += __n; return true; - } - - _T &back() const { return *(__end - 1); } - - bool equals_back(const PointerRange &__range) const { - return __end == __range.__end; - } - - ptrdiff_t distance_back(const PointerRange &__range) const { - return __range.__end - __end; - } - - /* satisfy FiniteRandomAccessRange */ - size_t size() const { return __end - __beg; } - - PointerRange slice(size_t __start, size_t __end) const { - return PointerRange(__beg + __start, __beg + __end); - } - - _T &operator[](size_t __i) const { return __beg[__i]; } - - /* satisfy OutputRange */ - void put(const _T &__v) { - *(__beg++) = __v; - } - void put(_T &&__v) { - *(__beg++) = octa::move(__v); - } - - private: - _T *__beg, *__end; - }; - - template - struct EnumeratedValue { - _S index; - _T value; - }; - - template - struct EnumeratedRange: InputRange, - CommonType, ForwardRangeTag>, RangeValue<_T>, - EnumeratedValue, RangeSize<_T>>, - RangeSize<_T> - > { - private: - typedef RangeReference<_T> _r_ref; - typedef RangeSize<_T> _r_size; - - _T __range; - _r_size __index; - - public: - EnumeratedRange(): __range(), __index(0) {} - - EnumeratedRange(const _T &__range): __range(__range), __index(0) {} - - EnumeratedRange(const EnumeratedRange &__it): - __range(__it.__range), __index(__it.__index) {} - - EnumeratedRange(EnumeratedRange &&__it): - __range(octa::move(__it.__range)), __index(__it.__index) {} - - EnumeratedRange &operator=(const EnumeratedRange &__v) { - __range = __v.__range; - __index = __v.__index; - return *this; - } - EnumeratedRange &operator=(EnumeratedRange &&__v) { - __range = octa::move(__v.__range); - __index = __v.__index; - return *this; - } - EnumeratedRange &operator=(const _T &__v) { - __range = __v; - __index = 0; - return *this; - } - EnumeratedRange &operator=(_T &&__v) { - __range = octa::move(__v); - __index = 0; - return *this; - } - - bool empty() const { return __range.empty(); } - - bool equals_front(const EnumeratedRange &__r) const { - return __range.equals_front(__r.__range); - } - - bool pop_front() { - if (__range.pop_front()) { - ++__index; - return true; - } - return false; - } - - _r_size pop_front_n(_r_size __n) { - _r_size __ret = __range.pop_front_n(__n); - __index += __ret; - return __ret; - } - - EnumeratedValue<_r_ref, _r_size> front() const { - return EnumeratedValue<_r_ref, _r_size> { __index, __range.front() }; - } - }; - - template - EnumeratedRange<_T> enumerate(const _T &__it) { - return EnumeratedRange<_T>(__it); - } - - template - struct TakeRange: InputRange, - CommonType, ForwardRangeTag>, - RangeValue<_T>, RangeReference<_T>, RangeSize<_T> - > { - private: - _T __range; - RangeSize<_T> __remaining; - public: - TakeRange(): __range(), __remaining(0) {} - TakeRange(const _T &__range, RangeSize<_T> __rem): __range(__range), - __remaining(__rem) {} - TakeRange(const TakeRange &__it): __range(__it.__range), - __remaining(__it.__remaining) {} - TakeRange(TakeRange &&__it): __range(octa::move(__it.__range)), - __remaining(__it.__remaining) {} - - TakeRange &operator=(const TakeRange &__v) { - __range = __v.__range; __remaining = __v.__remaining; return *this; - } - TakeRange &operator=(TakeRange &&__v) { - __range = octa::move(__v.__range); - __remaining = __v.__remaining; - return *this; - } - - bool empty() const { return (__remaining <= 0) || __range.empty(); } - - bool pop_front() { - if (__range.pop_front()) { - --__remaining; - return true; - } - return false; - } - bool push_front() { - if (__range.push_front()) { - ++__remaining; - return true; - } - return false; - } - - RangeSize<_T> pop_front_n(RangeSize<_T> __n) { - RangeSize<_T> __ret = __range.pop_front_n(__n); - __remaining -= __ret; - return __ret; - } - RangeSize<_T> push_front_n(RangeSize<_T> __n) { - RangeSize<_T> __ret = __range.push_front_n(__n); - __remaining += __ret; - return __ret; - } - - RangeReference<_T> front() const { return __range.front(); } - - bool equals_front(const TakeRange &__r) const { - return __range.equals_front(__r.__range); - } - - RangeDifference<_T> distance_front(const TakeRange &__r) const { - return __range.distance_front(__r.__range); - } - }; - - template - TakeRange<_T> take(const _T &__it, RangeSize<_T> __n) { - return TakeRange<_T>(__it, __n); - } - - template - struct ChunksRange: InputRange, - CommonType, ForwardRangeTag>, - TakeRange<_T>, TakeRange<_T>, RangeSize<_T> - > { - private: - _T __range; - RangeSize<_T> __chunksize; - public: - ChunksRange(): __range(), __chunksize(0) {} - ChunksRange(const _T &__range, RangeSize<_T> __chs): __range(__range), - __chunksize(__chs) {} - ChunksRange(const ChunksRange &__it): __range(__it.__range), - __chunksize(__it.__chunksize) {} - ChunksRange(ChunksRange &&__it): __range(octa::move(__it.__range)), - __chunksize(__it.__chunksize) {} - - ChunksRange &operator=(const ChunksRange &__v) { - __range = __v.__range; __chunksize = __v.p_chunksize; return *this; - } - ChunksRange &operator=(ChunksRange &&__v) { - __range = octa::move(__v.__range); - __chunksize = __v.__chunksize; - return *this; - } - - bool empty() const { return __range.empty(); } - - bool equals_front(const ChunksRange &__r) const { - return __range.equals_front(__r.__range); - } - - bool pop_front() { return __range.pop_front_n(__chunksize) > 0; } - bool push_front() { - _T __tmp = __range; - RangeSize<_T> __an = __tmp.push_front_n(__chunksize); - if (__an != __chunksize) return false; - __range = __tmp; - return true; - } - RangeSize<_T> pop_front_n(RangeSize<_T> __n) { - return __range.pop_front_n(__chunksize * __n) / __chunksize; - } - RangeSize<_T> push_front_n(RangeSize<_T> __n) { - _T __tmp = __range; - RangeSize<_T> __an = __tmp.push_front_n(__chunksize * __n); - RangeSize<_T> __pn = __an / __chunksize; - if (!__pn) return 0; - if (__pn == __n) { - __range = __tmp; - return __pn; - } - return __range.push_front_n(__chunksize * __an) / __chunksize; - } - - TakeRange<_T> front() const { return take(__range, __chunksize); } - }; - - template - ChunksRange<_T> chunks(const _T &__it, RangeSize<_T> __chs) { - return ChunksRange<_T>(__it, __chs); - } - - template - auto each(_T &__r) -> decltype(__r.each()) { - return __r.each(); - } - - template - auto each(const _T &__r) -> decltype(__r.each()) { - return __r.each(); - } - - template - PointerRange<_T> each(_T (&__array)[_N]) { - return PointerRange<_T>(__array, _N); - } - - // range of - template using RangeOf = decltype(octa::each(octa::declval<_T>())); - - template - struct HalfRange: InputRange, - RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>, - RangeDifference<_T> - > { - private: - _T __beg; - _T __end; - public: - HalfRange(): __beg(), __end() {} - HalfRange(const HalfRange &__range): __beg(__range.__beg), - __end(__range.__end) {} - HalfRange(HalfRange &&__range): __beg(octa::move(__range.__beg)), - __end(octa::move(__range.__end)) {} - HalfRange(const _T &__beg, const _T &__end): __beg(__beg), - __end(__end) {} - HalfRange(_T &&__beg, _T &&__end): __beg(octa::move(__beg)), - __end(octa::move(__end)) {} - - HalfRange &operator=(const HalfRange &__range) { - __beg = __range.p_beg; - __end = __range.p_end; - return *this; - } - - HalfRange &operator=(HalfRange &&__range) { - __beg = octa::move(__range.p_beg); - __end = octa::move(__range.p_end); - return *this; - } - - bool empty() const { return __beg == __end; } - - bool pop_front() { - if (empty()) return false; - return __beg.next(); - } - bool push_front() { - return __beg.prev(); - } - bool pop_back() { - if (empty()) return false; - return __end.prev(); - } - bool push_back() { - return __end.next(); - } - - RangeReference<_T> front() const { return *__beg; } - RangeReference<_T> back() const { return *(__end - 1); } - - bool equals_front(const HalfRange &__range) const { - return __beg == __range.__beg; - } - bool equals_back(const HalfRange &__range) const { - return __end == __range.__end; - } - - RangeDifference<_T> distance_front(const HalfRange &__range) const { - return __range.__beg - __beg; - } - RangeDifference<_T> distance_back(const HalfRange &__range) const { - return __range.__end - __end; - } - - RangeSize<_T> size() const { return __end - __beg; } - - HalfRange<_T> slice(RangeSize<_T> __start, RangeSize<_T> __end) const { - return HalfRange<_T>(__beg + __start, __beg + __end); - } - - RangeReference<_T> operator[](RangeSize<_T> __idx) const { - return __beg[__idx]; - } - - void put(const RangeValue<_T> &__v) { - __beg.range().put(__v); - } - void put(RangeValue<_T> &&__v) { - __beg.range().put(octa::move(__v)); - } - }; - - template - HalfRange> - make_half_range(const RangeHalf<_T> &__a, const RangeHalf<_T> &__b) { - return HalfRange>(__a, __b); + RangeSize<_R> push_back_n(_R &range, RangeSize<_R> n) { + for (RangeSize<_R> i = 0; i < n; ++i) + if (!range.push_back()) return i; + return n; } } +template struct InputRange { + typedef _C Category; + typedef _S Size; + typedef _D Difference; + typedef _V Value; + typedef _R Reference; + + octa::detail::RangeIterator<_B> begin() const { + return octa::detail::RangeIterator<_B>((const _B &)*this); + } + octa::detail::RangeIterator<_B> end() const { + return octa::detail::RangeIterator<_B>(); + } + + Size pop_front_n(Size n) { + return octa::detail::pop_front_n<_B>(*((_B *)this), n); + } + + Size pop_back_n(Size n) { + return octa::detail::pop_back_n<_B>(*((_B *)this), n); + } + + Size push_front_n(Size n) { + return octa::detail::push_front_n<_B>(*((_B *)this), n); + } + + Size push_back_n(Size n) { + return octa::detail::push_back_n<_B>(*((_B *)this), n); + } + + _B each() const { + return _B(*((_B *)this)); + } + + RangeHalf<_B> half() const { + return RangeHalf<_B>(*((_B *)this)); + } +}; + +template struct OutputRange { + typedef OutputRangeTag Category; + typedef _S Size; + typedef _D Difference; + typedef _V Value; + typedef _R Reference; +}; + +template +struct ReverseRange: InputRange, + RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>, + RangeDifference<_T> +> { +private: + typedef RangeReference<_T> _r_ref; + typedef RangeSize<_T> _r_size; + + _T p_range; + +public: + ReverseRange(): p_range() {} + + ReverseRange(const _T &range): p_range(range) {} + + ReverseRange(const ReverseRange &it): p_range(it.p_range) {} + + ReverseRange(ReverseRange &&it): p_range(octa::move(it.p_range)) {} + + ReverseRange &operator=(const ReverseRange &v) { + p_range = v.p_range; + return *this; + } + ReverseRange &operator=(ReverseRange &&v) { + p_range = octa::move(v.p_range); + return *this; + } + ReverseRange &operator=(const _T &v) { + p_range = v; + return *this; + } + ReverseRange &operator=(_T &&v) { + p_range = octa::move(v); + return *this; + } + + bool empty() const { return p_range.empty(); } + _r_size size() const { return p_range.size(); } + + bool equals_front(const ReverseRange &r) const { + return p_range.equals_back(r.p_range); + } + bool equals_back(const ReverseRange &r) const { + return p_range.equals_front(r.p_range); + } + + RangeDifference<_T> distance_front(const ReverseRange &r) const { + return -p_range.distance_back(r.p_range); + } + RangeDifference<_T> distance_back(const ReverseRange &r) const { + return -p_range.distance_front(r.p_range); + } + + bool pop_front() { return p_range.pop_back(); } + bool pop_back() { return p_range.pop_front(); } + + bool push_front() { return p_range.push_back(); } + bool push_back() { return p_range.push_front(); } + + _r_size pop_front_n(_r_size n) { return p_range.pop_front_n(n); } + _r_size pop_back_n(_r_size n) { return p_range.pop_back_n(n); } + + _r_size push_front_n(_r_size n) { return p_range.push_front_n(n); } + _r_size push_back_n(_r_size n) { return p_range.push_back_n(n); } + + _r_ref front() const { return p_range.back(); } + _r_ref back() const { return p_range.front(); } + + _r_ref operator[](_r_size i) const { return p_range[size() - i - 1]; } + + ReverseRange<_T> slice(_r_size start, _r_size end) const { + _r_size len = p_range.size(); + return ReverseRange<_T>(p_range.slice(len - end, len - start)); + } +}; + +template +ReverseRange<_T> make_reverse_range(const _T &it) { + return ReverseRange<_T>(it); +} + +template +struct MoveRange: InputRange, + RangeCategory<_T>, RangeValue<_T>, RangeValue<_T> &&, RangeSize<_T>, + RangeDifference<_T> +> { +private: + typedef RangeValue<_T> _r_val; + typedef RangeValue<_T> &&_r_ref; + typedef RangeSize<_T> _r_size; + + _T p_range; + +public: + MoveRange(): p_range() {} + + MoveRange(const _T &range): p_range(range) {} + + MoveRange(const MoveRange &it): p_range(it.p_range) {} + + MoveRange(MoveRange &&it): p_range(octa::move(it.p_range)) {} + + MoveRange &operator=(const MoveRange &v) { + p_range = v.p_range; + return *this; + } + MoveRange &operator=(MoveRange &&v) { + p_range = octa::move(v.p_range); + return *this; + } + MoveRange &operator=(const _T &v) { + p_range = v; + return *this; + } + MoveRange &operator=(_T &&v) { + p_range = octa::move(v); + return *this; + } + + bool empty() const { return p_range.empty(); } + _r_size size() const { return p_range.size(); } + + bool equals_front(const MoveRange &r) const { + return p_range.equals_front(r.p_range); + } + bool equals_back(const MoveRange &r) const { + return p_range.equals_back(r.p_range); + } + + RangeDifference<_T> distance_front(const MoveRange &r) const { + return p_range.distance_front(r.p_range); + } + RangeDifference<_T> distance_back(const MoveRange &r) const { + return p_range.distance_back(r.p_range); + } + + bool pop_front() { return p_range.pop_front(); } + bool pop_back() { return p_range.pop_back(); } + + bool push_front() { return p_range.push_front(); } + bool push_back() { return p_range.push_back(); } + + _r_size pop_front_n(_r_size n) { return p_range.pop_front_n(n); } + _r_size pop_back_n(_r_size n) { return p_range.pop_back_n(n); } + + _r_size push_front_n(_r_size n) { return p_range.push_front_n(n); } + _r_size push_back_n(_r_size n) { return p_range.push_back_n(n); } + + _r_ref front() const { return octa::move(p_range.front()); } + _r_ref back() const { return octa::move(p_range.back()); } + + _r_ref operator[](_r_size i) const { return octa::move(p_range[i]); } + + MoveRange<_T> slice(_r_size start, _r_size end) const { + return MoveRange<_T>(p_range.slice(start, end)); + } + + void put(const _r_val &v) { p_range.put(v); } + void put(_r_val &&v) { p_range.put(octa::move(v)); } +}; + +template +MoveRange<_T> make_move_range(const _T &it) { + return MoveRange<_T>(it); +} + +template +struct NumberRange: InputRange, ForwardRangeTag, _T, _T> { + NumberRange(): p_a(0), p_b(0), p_step(0) {} + NumberRange(const NumberRange &it): p_a(it.p_a), p_b(it.p_b), + p_step(it.p_step) {} + NumberRange(_T a, _T b, _T step = _T(1)): p_a(a), p_b(b), + p_step(step) {} + NumberRange(_T v): p_a(0), p_b(v), p_step(1) {} + + bool empty() const { return p_a * p_step >= p_b * p_step; } + + bool equals_front(const NumberRange &range) const { + return p_a == range.p_a; + } + + bool pop_front() { p_a += p_step; return true; } + bool push_front() { p_a -= p_step; return true; } + _T front() const { return p_a; } + +private: + _T p_a, p_b, p_step; +}; + +template +NumberRange<_T> range(_T a, _T b, _T step = _T(1)) { + return NumberRange<_T>(a, b, step); +} + +template +NumberRange<_T> range(_T v) { + return NumberRange<_T>(v); +} + +template +struct PointerRange: InputRange, FiniteRandomAccessRangeTag, _T> { + PointerRange(): p_beg(nullptr), p_end(nullptr) {} + PointerRange(const PointerRange &v): p_beg(v.p_beg), + p_end(v.p_end) {} + PointerRange(_T *beg, _T *end): p_beg(beg), p_end(end) {} + PointerRange(_T *beg, size_t n): p_beg(beg), p_end(beg + n) {} + + PointerRange &operator=(const PointerRange &v) { + p_beg = v.p_beg; + p_end = 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; + } + + size_t pop_front_n(size_t n) { + size_t olen = p_end - p_beg; + p_beg += n; + if (p_beg > p_end) { + p_beg = p_end; + return olen; + } + return n; + } + + size_t push_front_n(size_t n) { + p_beg -= n; return true; + } + + _T &front() const { return *p_beg; } + + bool equals_front(const PointerRange &range) const { + return p_beg == range.p_beg; + } + + ptrdiff_t distance_front(const PointerRange &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; + } + + size_t pop_back_n(size_t n) { + size_t olen = p_end - p_beg; + p_end -= n; + if (p_end < p_beg) { + p_end = p_beg; + return olen; + } + return n; + } + + size_t push_back_n(size_t n) { + p_end += n; return true; + } + + _T &back() const { return *(p_end - 1); } + + bool equals_back(const PointerRange &range) const { + return p_end == range.p_end; + } + + ptrdiff_t distance_back(const PointerRange &range) const { + return range.p_end - p_end; + } + + /* satisfy FiniteRandomAccessRange */ + size_t size() const { return p_end - p_beg; } + + PointerRange slice(size_t start, size_t end) const { + return PointerRange(p_beg + start, p_beg + end); + } + + _T &operator[](size_t i) const { return p_beg[i]; } + + /* satisfy OutputRange */ + void put(const _T &v) { + *(p_beg++) = v; + } + void put(_T &&v) { + *(p_beg++) = octa::move(v); + } + +private: + _T *p_beg, *p_end; +}; + +template +struct EnumeratedValue { + _S index; + _T value; +}; + +template +struct EnumeratedRange: InputRange, + CommonType, ForwardRangeTag>, RangeValue<_T>, + EnumeratedValue, RangeSize<_T>>, + RangeSize<_T> +> { +private: + typedef RangeReference<_T> _r_ref; + typedef RangeSize<_T> _r_size; + + _T p_range; + _r_size p_index; + +public: + EnumeratedRange(): p_range(), p_index(0) {} + + EnumeratedRange(const _T &range): p_range(range), p_index(0) {} + + EnumeratedRange(const EnumeratedRange &it): + p_range(it.p_range), p_index(it.p_index) {} + + EnumeratedRange(EnumeratedRange &&it): + p_range(octa::move(it.p_range)), p_index(it.p_index) {} + + EnumeratedRange &operator=(const EnumeratedRange &v) { + p_range = v.p_range; + p_index = v.p_index; + return *this; + } + EnumeratedRange &operator=(EnumeratedRange &&v) { + p_range = octa::move(v.p_range); + p_index = v.p_index; + return *this; + } + EnumeratedRange &operator=(const _T &v) { + p_range = v; + p_index = 0; + return *this; + } + EnumeratedRange &operator=(_T &&v) { + p_range = octa::move(v); + p_index = 0; + return *this; + } + + bool empty() const { return p_range.empty(); } + + bool equals_front(const EnumeratedRange &r) const { + return p_range.equals_front(r.p_range); + } + + bool pop_front() { + if (p_range.pop_front()) { + ++p_index; + return true; + } + return false; + } + + _r_size pop_front_n(_r_size n) { + _r_size ret = p_range.pop_front_n(n); + p_index += ret; + return ret; + } + + EnumeratedValue<_r_ref, _r_size> front() const { + return EnumeratedValue<_r_ref, _r_size> { p_index, p_range.front() }; + } +}; + +template +EnumeratedRange<_T> enumerate(const _T &it) { + return EnumeratedRange<_T>(it); +} + +template +struct TakeRange: InputRange, + CommonType, ForwardRangeTag>, + RangeValue<_T>, RangeReference<_T>, RangeSize<_T> +> { +private: + _T p_range; + RangeSize<_T> p_remaining; +public: + TakeRange(): p_range(), p_remaining(0) {} + TakeRange(const _T &range, RangeSize<_T> rem): p_range(range), + p_remaining(rem) {} + TakeRange(const TakeRange &it): p_range(it.p_range), + p_remaining(it.p_remaining) {} + TakeRange(TakeRange &&it): p_range(octa::move(it.p_range)), + p_remaining(it.p_remaining) {} + + TakeRange &operator=(const TakeRange &v) { + p_range = v.p_range; p_remaining = v.p_remaining; return *this; + } + TakeRange &operator=(TakeRange &&v) { + p_range = octa::move(v.p_range); + p_remaining = v.p_remaining; + return *this; + } + + bool empty() const { return (p_remaining <= 0) || p_range.empty(); } + + bool pop_front() { + if (p_range.pop_front()) { + --p_remaining; + return true; + } + return false; + } + bool push_front() { + if (p_range.push_front()) { + ++p_remaining; + return true; + } + return false; + } + + RangeSize<_T> pop_front_n(RangeSize<_T> n) { + RangeSize<_T> ret = p_range.pop_front_n(n); + p_remaining -= ret; + return ret; + } + RangeSize<_T> push_front_n(RangeSize<_T> n) { + RangeSize<_T> ret = p_range.push_front_n(n); + p_remaining += ret; + return ret; + } + + RangeReference<_T> front() const { return p_range.front(); } + + bool equals_front(const TakeRange &r) const { + return p_range.equals_front(r.p_range); + } + + RangeDifference<_T> distance_front(const TakeRange &r) const { + return p_range.distance_front(r.p_range); + } +}; + +template +TakeRange<_T> take(const _T &it, RangeSize<_T> n) { + return TakeRange<_T>(it, n); +} + +template +struct ChunksRange: InputRange, + CommonType, ForwardRangeTag>, + TakeRange<_T>, TakeRange<_T>, RangeSize<_T> +> { +private: + _T p_range; + RangeSize<_T> p_chunksize; +public: + ChunksRange(): p_range(), p_chunksize(0) {} + ChunksRange(const _T &range, RangeSize<_T> chs): p_range(range), + p_chunksize(chs) {} + ChunksRange(const ChunksRange &it): p_range(it.p_range), + p_chunksize(it.p_chunksize) {} + ChunksRange(ChunksRange &&it): p_range(octa::move(it.p_range)), + p_chunksize(it.p_chunksize) {} + + ChunksRange &operator=(const ChunksRange &v) { + p_range = v.p_range; p_chunksize = v.p_chunksize; return *this; + } + ChunksRange &operator=(ChunksRange &&v) { + p_range = octa::move(v.p_range); + p_chunksize = v.p_chunksize; + return *this; + } + + bool empty() const { return p_range.empty(); } + + bool equals_front(const ChunksRange &r) const { + return p_range.equals_front(r.p_range); + } + + bool pop_front() { return p_range.pop_front_n(p_chunksize) > 0; } + bool push_front() { + _T tmp = p_range; + RangeSize<_T> an = tmp.push_front_n(p_chunksize); + if (an != p_chunksize) return false; + p_range = tmp; + return true; + } + RangeSize<_T> pop_front_n(RangeSize<_T> n) { + return p_range.pop_front_n(p_chunksize * n) / p_chunksize; + } + RangeSize<_T> push_front_n(RangeSize<_T> n) { + _T tmp = p_range; + RangeSize<_T> an = tmp.push_front_n(p_chunksize * n); + RangeSize<_T> pn = an / p_chunksize; + if (!pn) return 0; + if (pn == n) { + p_range = tmp; + return pn; + } + return p_range.push_front_n(p_chunksize * an) / p_chunksize; + } + + TakeRange<_T> front() const { return take(p_range, p_chunksize); } +}; + +template +ChunksRange<_T> chunks(const _T &it, RangeSize<_T> chs) { + return ChunksRange<_T>(it, chs); +} + +template +auto each(_T &r) -> decltype(r.each()) { + return r.each(); +} + +template +auto each(const _T &r) -> decltype(r.each()) { + return r.each(); +} + +template +PointerRange<_T> each(_T (&array)[_N]) { + return PointerRange<_T>(array, _N); +} + +// range of +template using RangeOf = decltype(octa::each(octa::declval<_T>())); + +template +struct HalfRange: InputRange, + RangeCategory<_T>, RangeValue<_T>, RangeReference<_T>, RangeSize<_T>, + RangeDifference<_T> +> { +private: + _T p_beg; + _T p_end; +public: + HalfRange(): p_beg(), p_end() {} + HalfRange(const HalfRange &range): p_beg(range.p_beg), + p_end(range.p_end) {} + HalfRange(HalfRange &&range): p_beg(octa::move(range.p_beg)), + p_end(octa::move(range.p_end)) {} + HalfRange(const _T &beg, const _T &end): p_beg(beg), + p_end(end) {} + HalfRange(_T &&beg, _T &&end): p_beg(octa::move(beg)), + p_end(octa::move(end)) {} + + HalfRange &operator=(const HalfRange &range) { + p_beg = range.p_beg; + p_end = range.p_end; + return *this; + } + + HalfRange &operator=(HalfRange &&range) { + p_beg = octa::move(range.p_beg); + p_end = octa::move(range.p_end); + return *this; + } + + bool empty() const { return p_beg == p_end; } + + bool pop_front() { + if (empty()) return false; + return p_beg.next(); + } + bool push_front() { + return p_beg.prev(); + } + bool pop_back() { + if (empty()) return false; + return p_end.prev(); + } + bool push_back() { + return p_end.next(); + } + + RangeReference<_T> front() const { return *p_beg; } + RangeReference<_T> back() const { return *(p_end - 1); } + + bool equals_front(const HalfRange &range) const { + return p_beg == range.p_beg; + } + bool equals_back(const HalfRange &range) const { + return p_end == range.p_end; + } + + RangeDifference<_T> distance_front(const HalfRange &range) const { + return range.p_beg - p_beg; + } + RangeDifference<_T> distance_back(const HalfRange &range) const { + return range.p_end - p_end; + } + + RangeSize<_T> size() const { return p_end - p_beg; } + + HalfRange<_T> slice(RangeSize<_T> start, RangeSize<_T> p_end) const { + return HalfRange<_T>(p_beg + start, p_beg + p_end); + } + + RangeReference<_T> operator[](RangeSize<_T> idx) const { + return p_beg[idx]; + } + + void put(const RangeValue<_T> &v) { + p_beg.range().put(v); + } + void put(RangeValue<_T> &&v) { + p_beg.range().put(octa::move(v)); + } +}; + +template +HalfRange> +make_half_range(const RangeHalf<_T> &a, const RangeHalf<_T> &b) { + return HalfRange>(a, b); +} + +} /* namespace octa */ + #endif \ No newline at end of file