allow range traits to work on halves

master
Daniel Kolesa 2015-05-29 23:48:05 +01:00
parent 3c6ef6e593
commit cb1bf48aaa
1 changed files with 32 additions and 23 deletions

View File

@ -20,11 +20,27 @@ namespace octa {
struct RandomAccessRangeTag: BidirectionalRangeTag {}; struct RandomAccessRangeTag: BidirectionalRangeTag {};
struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {}; struct FiniteRandomAccessRangeTag: RandomAccessRangeTag {};
template<typename T> using RangeCategory = typename T::Category; template<typename T> struct RangeHalf;
template<typename T> using RangeSize = typename T::SizeType;
template<typename T> using RangeValue = typename T::ValType; #define __OCTA_RANGE_TRAIT(Name, TypeName) \
template<typename T> using RangeReference = typename T::RefType; template<typename T> \
template<typename T> using RangeDifference = typename T::DiffType; struct __OctaRange##Name { \
typedef typename T::TypeName Type; \
}; \
template<typename T> \
struct __OctaRange##Name<RangeHalf<T>> { \
typedef typename T::TypeName Type; \
}; \
template<typename T> \
using Range##Name = typename __OctaRange##Name<T>::Type;
__OCTA_RANGE_TRAIT(Category, Category)
__OCTA_RANGE_TRAIT(Size, SizeType)
__OCTA_RANGE_TRAIT(Value, ValType)
__OCTA_RANGE_TRAIT(Reference, RefType)
__OCTA_RANGE_TRAIT(Difference, DiffType)
#undef __OCTA_RANGE_TRAIT
// is input range // is input range
@ -847,11 +863,8 @@ namespace octa {
template<typename T> template<typename T>
struct HalfRange: InputRange<HalfRange<T>, struct HalfRange: InputRange<HalfRange<T>,
RangeCategory <typename T::RangeType>, RangeCategory<T>, RangeValue<T>, RangeReference<T>, RangeSize<T>,
RangeValue <typename T::RangeType>, RangeDifference<T>
RangeReference <typename T::RangeType>,
RangeSize <typename T::RangeType>,
RangeDifference<typename T::RangeType>
> { > {
private: private:
T p_beg; T p_beg;
@ -894,10 +907,10 @@ namespace octa {
return p_end.next(); return p_end.next();
} }
RangeReference<typename T::RangeType> first() const { RangeReference<T> first() const {
return p_beg.get(); return p_beg.get();
} }
RangeReference<typename T::RangeType> last() const { RangeReference<T> last() const {
auto copy = p_end; auto copy = p_end;
copy.prev(); copy.prev();
return copy.get(); return copy.get();
@ -910,33 +923,29 @@ namespace octa {
return p_end == range.p_end; return p_end == range.p_end;
} }
RangeDifference<typename T::RangeType> RangeDifference<T> distance_first(const HalfRange &range) const {
distance_first(const HalfRange &range) const {
return p_beg.distance(range.p_beg); return p_beg.distance(range.p_beg);
} }
RangeDifference<typename T::RangeType> RangeDifference<T> distance_last(const HalfRange &range) const {
distance_last(const HalfRange &range) const {
return p_end.distance(range.p_end); return p_end.distance(range.p_end);
} }
RangeSize<typename T::RangeType> size() { RangeSize<T> size() const {
return p_end - p_beg; return p_end - p_beg;
} }
HalfRange<T> slice(RangeSize<typename T::RangeType> start, HalfRange<T> slice(RangeSize<T> start, RangeSize<T> end) const {
RangeSize<typename T::RangeType> end) {
return HalfRange<T>(p_beg + start, p_beg + end); return HalfRange<T>(p_beg + start, p_beg + end);
} }
RangeReference<typename T::RangeType> RangeReference<T> operator[](RangeSize<T> idx) const {
operator[](RangeSize<typename T::RangeType> idx) {
return p_beg[idx]; return p_beg[idx];
} }
void put(const RangeValue<typename T::RangeType> &v) { void put(const RangeValue<T> &v) {
p_beg.range().put(v); p_beg.range().put(v);
} }
void put(RangeValue<typename T::RangeType> &&v) { void put(RangeValue<T> &&v) {
p_beg.range().put(move(v)); p_beg.range().put(move(v));
} }
}; };