forked from OctaForge/libostd
convert range checks to template vars
This commit is contained in:
parent
9b11c1d319
commit
a6744105dc
|
@ -27,14 +27,14 @@ namespace detail {
|
|||
|
||||
template<typename R>
|
||||
static inline Size estimate_hrsize(const R &range,
|
||||
EnableIf<IsFiniteRandomAccessRange<R>::value, bool> = true
|
||||
EnableIf<IsFiniteRandomAccessRange<R>, bool> = true
|
||||
) {
|
||||
return range.size();
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
static inline Size estimate_hrsize(const R &,
|
||||
EnableIf<!IsFiniteRandomAccessRange<R>::value, bool> = true
|
||||
EnableIf<!IsFiniteRandomAccessRange<R>, bool> = true
|
||||
) {
|
||||
/* we have no idea how big the range actually is */
|
||||
return 16;
|
||||
|
|
|
@ -86,8 +86,7 @@ namespace detail {
|
|||
KeysetImpl(KeysetImpl &&m, const A &alloc): Base(move(m), alloc) {}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value && IsConvertible<RangeReference<R>,
|
||||
Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> KeysetImpl(R range, Size size = 0, const H &hf = H(),
|
||||
const C &eqf = C(), const A &alloc = A()
|
||||
): Base(size ? size : detail::estimate_hrsize(range),
|
||||
|
@ -127,8 +126,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> KeysetImpl &operator=(R range) {
|
||||
Base::assign_range(range);
|
||||
return *this;
|
||||
|
|
|
@ -86,8 +86,7 @@ namespace detail {
|
|||
MapImpl(MapImpl &&m, const A &alloc): Base(move(m), alloc) {}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value && IsConvertible<RangeReference<R>,
|
||||
Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> MapImpl(R range, Size size = 0, const H &hf = H(),
|
||||
const C &eqf = C(), const A &alloc = A()
|
||||
): Base(size ? size : detail::estimate_hrsize(range),
|
||||
|
@ -127,8 +126,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> MapImpl &operator=(R range) {
|
||||
Base::assign_range(range);
|
||||
return *this;
|
||||
|
|
122
ostd/range.hh
122
ostd/range.hh
|
@ -73,113 +73,129 @@ namespace detail {
|
|||
namespace detail {
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, InputRangeTag
|
||||
>::value> struct IsInputRangeBase: False {};
|
||||
>::value> struct IsInputRangeCore: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsInputRangeBase<T, true>: True {};
|
||||
}
|
||||
struct IsInputRangeCore<T, true>: True {};
|
||||
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsInputRange: False {};
|
||||
struct IsInputRangeBase: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsInputRange<T, true>: detail::IsInputRangeBase<T>::Type {};
|
||||
struct IsInputRangeBase<T, true>: detail::IsInputRangeCore<T>::Type {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr bool IsInputRange = detail::IsInputRangeBase<T>::value;
|
||||
|
||||
// is forward range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, ForwardRangeTag
|
||||
>::value> struct IsForwardRangeBase: False {};
|
||||
>::value> struct IsForwardRangeCore: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsForwardRangeBase<T, true>: True {};
|
||||
}
|
||||
struct IsForwardRangeCore<T, true>: True {};
|
||||
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsForwardRange: False {};
|
||||
struct IsForwardRangeBase: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsForwardRange<T, true>: detail::IsForwardRangeBase<T>::Type {};
|
||||
struct IsForwardRangeBase<T, true>: detail::IsForwardRangeCore<T>::Type {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr bool IsForwardRange = detail::IsForwardRangeBase<T>::value;
|
||||
|
||||
// is bidirectional range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, BidirectionalRangeTag
|
||||
>::value> struct IsBidirectionalRangeBase: False {};
|
||||
>::value> struct IsBidirectionalRangeCore: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsBidirectionalRangeBase<T, true>: True {};
|
||||
}
|
||||
struct IsBidirectionalRangeCore<T, true>: True {};
|
||||
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsBidirectionalRange: False {};
|
||||
struct IsBidirectionalRangeBase: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsBidirectionalRange<T, true>:
|
||||
detail::IsBidirectionalRangeBase<T>::Type {};
|
||||
struct IsBidirectionalRangeBase<T, true>:
|
||||
detail::IsBidirectionalRangeCore<T>::Type {};
|
||||
}
|
||||
|
||||
template<typename T> static constexpr bool IsBidirectionalRange
|
||||
= detail::IsBidirectionalRangeBase<T>::value;
|
||||
|
||||
// is random access range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, RandomAccessRangeTag
|
||||
>::value> struct IsRandomAccessRangeBase: False {};
|
||||
>::value> struct IsRandomAccessRangeCore: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsRandomAccessRangeBase<T, true>: True {};
|
||||
}
|
||||
struct IsRandomAccessRangeCore<T, true>: True {};
|
||||
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsRandomAccessRange: False {};
|
||||
struct IsRandomAccessRangeBase: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsRandomAccessRange<T, true>:
|
||||
detail::IsRandomAccessRangeBase<T>::Type {};
|
||||
struct IsRandomAccessRangeBase<T, true>:
|
||||
detail::IsRandomAccessRangeCore<T>::Type {};
|
||||
}
|
||||
|
||||
template<typename T> static constexpr bool IsRandomAccessRange
|
||||
= detail::IsRandomAccessRangeBase<T>::value;
|
||||
|
||||
// is finite random access range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, FiniteRandomAccessRangeTag
|
||||
>::value> struct IsFiniteRandomAccessRangeBase: False {};
|
||||
>::value> struct IsFiniteRandomAccessRangeCore: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsFiniteRandomAccessRangeBase<T, true>: True {};
|
||||
}
|
||||
struct IsFiniteRandomAccessRangeCore<T, true>: True {};
|
||||
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsFiniteRandomAccessRange: False {};
|
||||
struct IsFiniteRandomAccessRangeBase: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsFiniteRandomAccessRange<T, true>:
|
||||
detail::IsFiniteRandomAccessRangeBase<T>::Type {};
|
||||
struct IsFiniteRandomAccessRangeBase<T, true>:
|
||||
detail::IsFiniteRandomAccessRangeCore<T>::Type {};
|
||||
}
|
||||
|
||||
template<typename T> static constexpr bool IsFiniteRandomAccessRange
|
||||
= detail::IsFiniteRandomAccessRangeBase<T>::value;
|
||||
|
||||
// is infinite random access range
|
||||
|
||||
template<typename T>
|
||||
struct IsInfiniteRandomAccessRange: IntegralConstant<bool,
|
||||
(IsRandomAccessRange<T>::value && !IsFiniteRandomAccessRange<T>::value)
|
||||
> {};
|
||||
template<typename T> static constexpr bool IsInfiniteRandomAccessRange
|
||||
= IsRandomAccessRange<T> && !IsFiniteRandomAccessRange<T>;
|
||||
|
||||
// is contiguous range
|
||||
|
||||
namespace detail {
|
||||
template<typename T, bool = IsConvertible<
|
||||
RangeCategory<T>, ContiguousRangeTag
|
||||
>::value> struct IsContiguousRangeBase: False {};
|
||||
>::value> struct IsContiguousRangeCore: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsContiguousRangeBase<T, true>: True {};
|
||||
}
|
||||
struct IsContiguousRangeCore<T, true>: True {};
|
||||
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsContiguousRange: False {};
|
||||
struct IsContiguousRangeBase: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsContiguousRange<T, true>:
|
||||
detail::IsContiguousRangeBase<T>::Type {};
|
||||
struct IsContiguousRangeBase<T, true>:
|
||||
detail::IsContiguousRangeCore<T>::Type {};
|
||||
}
|
||||
|
||||
template<typename T> static constexpr bool IsContiguousRange
|
||||
= detail::IsContiguousRangeBase<T>::value;
|
||||
|
||||
// is output range
|
||||
|
||||
|
@ -191,18 +207,28 @@ namespace detail {
|
|||
template<typename U> static int test(...);
|
||||
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T, bool = (IsConvertible<
|
||||
RangeCategory<T>, OutputRangeTag
|
||||
>::value || (IsInputRange<T>::value &&
|
||||
>::value || (IsInputRange<T> &&
|
||||
(detail::OutputRangeTest<T, const RangeValue<T> &>::value ||
|
||||
detail::OutputRangeTest<T, RangeValue<T> &&>::value ||
|
||||
detail::OutputRangeTest<T, RangeValue<T> >::value)
|
||||
))> struct IsOutputRange: False {};
|
||||
))> struct IsOutputRangeCore: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsOutputRange<T, true>: True {};
|
||||
struct IsOutputRangeCore<T, true>: True {};
|
||||
|
||||
template<typename T, bool = detail::IsRangeTest<T>::value>
|
||||
struct IsOutputRangeBase: False {};
|
||||
|
||||
template<typename T>
|
||||
struct IsOutputRangeBase<T, true>:
|
||||
detail::IsOutputRangeCore<T>::Type {};
|
||||
}
|
||||
|
||||
template<typename T> static constexpr bool IsOutputRange
|
||||
= detail::IsOutputRangeBase<T>::value;
|
||||
|
||||
namespace detail {
|
||||
// range iterator
|
||||
|
@ -236,7 +262,7 @@ namespace detail {
|
|||
template<typename T> struct HalfRange;
|
||||
|
||||
namespace detail {
|
||||
template<typename R, bool = IsBidirectionalRange<typename R::Range>::value>
|
||||
template<typename R, bool = IsBidirectionalRange<typename R::Range>>
|
||||
struct RangeAdd;
|
||||
|
||||
template<typename R>
|
||||
|
@ -484,9 +510,8 @@ template<typename B, typename C, typename V, typename R = V &,
|
|||
return (on - n);
|
||||
}
|
||||
|
||||
template<typename OR,
|
||||
typename = EnableIf<IsOutputRange<OR>::value>
|
||||
> Size copy(OR &&orange, Size n = -1) {
|
||||
template<typename OR, typename = EnableIf<IsOutputRange<OR>>>
|
||||
Size copy(OR &&orange, Size n = -1) {
|
||||
B r(*((B *)this));
|
||||
Size on = n;
|
||||
for (; n && !r.empty(); --n) {
|
||||
|
@ -995,9 +1020,8 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
template<typename R,
|
||||
typename = EnableIf<IsOutputRange<R>::value
|
||||
>> Size copy(R &&orange, Size n = -1) {
|
||||
template<typename R, typename = EnableIf<IsOutputRange<R>>>
|
||||
Size copy(R &&orange, Size n = -1) {
|
||||
Size c = size();
|
||||
if (n < c) c = n;
|
||||
return orange.put_n(p_beg, c);
|
||||
|
|
|
@ -75,8 +75,7 @@ namespace detail {
|
|||
SetImpl(SetImpl &&m, const A &alloc): Base(move(m), alloc) {}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> SetImpl(R range, Size size = 0, const H &hf = H(),
|
||||
const C &eqf = C(), const A &alloc = A()
|
||||
): Base(size ? size : detail::estimate_hrsize(range),
|
||||
|
@ -116,8 +115,7 @@ namespace detail {
|
|||
}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> SetImpl &operator=(R range) {
|
||||
Base::assign_range(range);
|
||||
return *this;
|
||||
|
|
|
@ -209,8 +209,7 @@ class StringBase {
|
|||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<
|
||||
IsFiniteRandomAccessRange<R>::value &&
|
||||
IsSame<T, RemoveCv<RangeValue<R>>>, bool
|
||||
IsFiniteRandomAccessRange<R> && IsSame<T, RemoveCv<RangeValue<R>>>, bool
|
||||
> = true) {
|
||||
if (range.empty()) return;
|
||||
RangeSize<R> l = range.size();
|
||||
|
@ -222,8 +221,8 @@ class StringBase {
|
|||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<
|
||||
!IsFiniteRandomAccessRange<R>::value ||
|
||||
!IsSame<T, RemoveCv<RangeValue<R>>>, bool
|
||||
!IsFiniteRandomAccessRange<R> || !IsSame<T, RemoveCv<RangeValue<R>>>,
|
||||
bool
|
||||
> = true) {
|
||||
if (range.empty()) return;
|
||||
Size i = 0;
|
||||
|
@ -327,8 +326,7 @@ public:
|
|||
> &a = A()): StringBase(ConstRange(v), a) {}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> StringBase(R range, const A &a = A()): StringBase(a) {
|
||||
ctor_from_range(range);
|
||||
}
|
||||
|
@ -400,8 +398,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> StringBase &operator=(const R &r) {
|
||||
clear();
|
||||
ctor_from_range(r);
|
||||
|
@ -503,7 +500,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsInputRange<R> &&
|
||||
IsConvertible<RangeReference<R>, Value>::value &&
|
||||
!IsConvertible<R, ConstRange>::value
|
||||
>> StringBase &append(R range) {
|
||||
|
|
|
@ -35,7 +35,7 @@ class Vector {
|
|||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<
|
||||
IsFiniteRandomAccessRange<R>::value && IsPod<T> &&
|
||||
IsFiniteRandomAccessRange<R> && IsPod<T> &&
|
||||
IsSame<T, RemoveCv<RangeValue<R>>>, bool
|
||||
> = true) {
|
||||
RangeSize<R> l = range.size();
|
||||
|
@ -46,7 +46,7 @@ class Vector {
|
|||
|
||||
template<typename R>
|
||||
void ctor_from_range(R &range, EnableIf<
|
||||
!IsFiniteRandomAccessRange<R>::value || !IsPod<T> ||
|
||||
!IsFiniteRandomAccessRange<R> || !IsPod<T> ||
|
||||
!IsSame<T, RemoveCv<RangeValue<R>>>, bool
|
||||
> = true) {
|
||||
Size i = 0;
|
||||
|
@ -151,8 +151,7 @@ public:
|
|||
Vector(ConstRange(v.begin(), v.size()), a) {}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> Vector(R range, const A &a = A()): Vector(a) {
|
||||
ctor_from_range(range);
|
||||
}
|
||||
|
@ -219,8 +218,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename R, typename = EnableIf<
|
||||
IsInputRange<R>::value &&
|
||||
IsConvertible<RangeReference<R>, Value>::value
|
||||
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
|
||||
>> Vector &operator=(R range) {
|
||||
clear();
|
||||
ctor_from_range(range);
|
||||
|
|
Loading…
Reference in a new issue