convert range checks to template vars

master
Daniel Kolesa 2016-01-13 17:42:37 +00:00
parent 9b11c1d319
commit a6744105dc
7 changed files with 107 additions and 94 deletions

View File

@ -27,14 +27,14 @@ namespace detail {
template<typename R> template<typename R>
static inline Size estimate_hrsize(const R &range, static inline Size estimate_hrsize(const R &range,
EnableIf<IsFiniteRandomAccessRange<R>::value, bool> = true EnableIf<IsFiniteRandomAccessRange<R>, bool> = true
) { ) {
return range.size(); return range.size();
} }
template<typename R> template<typename R>
static inline Size estimate_hrsize(const 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 */ /* we have no idea how big the range actually is */
return 16; return 16;

View File

@ -86,8 +86,7 @@ namespace detail {
KeysetImpl(KeysetImpl &&m, const A &alloc): Base(move(m), alloc) {} KeysetImpl(KeysetImpl &&m, const A &alloc): Base(move(m), alloc) {}
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsConvertible<RangeReference<R>, IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
Value>::value
>> KeysetImpl(R range, Size size = 0, const H &hf = H(), >> KeysetImpl(R range, Size size = 0, const H &hf = H(),
const C &eqf = C(), const A &alloc = A() const C &eqf = C(), const A &alloc = A()
): Base(size ? size : detail::estimate_hrsize(range), ): Base(size ? size : detail::estimate_hrsize(range),
@ -127,8 +126,7 @@ namespace detail {
} }
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> KeysetImpl &operator=(R range) { >> KeysetImpl &operator=(R range) {
Base::assign_range(range); Base::assign_range(range);
return *this; return *this;

View File

@ -86,8 +86,7 @@ namespace detail {
MapImpl(MapImpl &&m, const A &alloc): Base(move(m), alloc) {} MapImpl(MapImpl &&m, const A &alloc): Base(move(m), alloc) {}
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsConvertible<RangeReference<R>, IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
Value>::value
>> MapImpl(R range, Size size = 0, const H &hf = H(), >> MapImpl(R range, Size size = 0, const H &hf = H(),
const C &eqf = C(), const A &alloc = A() const C &eqf = C(), const A &alloc = A()
): Base(size ? size : detail::estimate_hrsize(range), ): Base(size ? size : detail::estimate_hrsize(range),
@ -127,8 +126,7 @@ namespace detail {
} }
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> MapImpl &operator=(R range) { >> MapImpl &operator=(R range) {
Base::assign_range(range); Base::assign_range(range);
return *this; return *this;

View File

@ -73,113 +73,129 @@ namespace detail {
namespace detail { namespace detail {
template<typename T, bool = IsConvertible< template<typename T, bool = IsConvertible<
RangeCategory<T>, InputRangeTag RangeCategory<T>, InputRangeTag
>::value> struct IsInputRangeBase: False {}; >::value> struct IsInputRangeCore: False {};
template<typename T> template<typename T>
struct IsInputRangeBase<T, true>: True {}; struct IsInputRangeCore<T, true>: True {};
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsInputRangeBase: False {};
template<typename T>
struct IsInputRangeBase<T, true>: detail::IsInputRangeCore<T>::Type {};
} }
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsInputRange: False {};
template<typename T> template<typename T>
struct IsInputRange<T, true>: detail::IsInputRangeBase<T>::Type {}; static constexpr bool IsInputRange = detail::IsInputRangeBase<T>::value;
// is forward range // is forward range
namespace detail { namespace detail {
template<typename T, bool = IsConvertible< template<typename T, bool = IsConvertible<
RangeCategory<T>, ForwardRangeTag RangeCategory<T>, ForwardRangeTag
>::value> struct IsForwardRangeBase: False {}; >::value> struct IsForwardRangeCore: False {};
template<typename T> template<typename T>
struct IsForwardRangeBase<T, true>: True {}; struct IsForwardRangeCore<T, true>: True {};
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsForwardRangeBase: False {};
template<typename T>
struct IsForwardRangeBase<T, true>: detail::IsForwardRangeCore<T>::Type {};
} }
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsForwardRange: False {};
template<typename T> template<typename T>
struct IsForwardRange<T, true>: detail::IsForwardRangeBase<T>::Type {}; static constexpr bool IsForwardRange = detail::IsForwardRangeBase<T>::value;
// is bidirectional range // is bidirectional range
namespace detail { namespace detail {
template<typename T, bool = IsConvertible< template<typename T, bool = IsConvertible<
RangeCategory<T>, BidirectionalRangeTag RangeCategory<T>, BidirectionalRangeTag
>::value> struct IsBidirectionalRangeBase: False {}; >::value> struct IsBidirectionalRangeCore: False {};
template<typename T> template<typename T>
struct IsBidirectionalRangeBase<T, true>: True {}; struct IsBidirectionalRangeCore<T, true>: True {};
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsBidirectionalRangeBase: False {};
template<typename T>
struct IsBidirectionalRangeBase<T, true>:
detail::IsBidirectionalRangeCore<T>::Type {};
} }
template<typename T, bool = detail::IsRangeTest<T>::value> template<typename T> static constexpr bool IsBidirectionalRange
struct IsBidirectionalRange: False {}; = detail::IsBidirectionalRangeBase<T>::value;
template<typename T>
struct IsBidirectionalRange<T, true>:
detail::IsBidirectionalRangeBase<T>::Type {};
// is random access range // is random access range
namespace detail { namespace detail {
template<typename T, bool = IsConvertible< template<typename T, bool = IsConvertible<
RangeCategory<T>, RandomAccessRangeTag RangeCategory<T>, RandomAccessRangeTag
>::value> struct IsRandomAccessRangeBase: False {}; >::value> struct IsRandomAccessRangeCore: False {};
template<typename T> template<typename T>
struct IsRandomAccessRangeBase<T, true>: True {}; struct IsRandomAccessRangeCore<T, true>: True {};
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsRandomAccessRangeBase: False {};
template<typename T>
struct IsRandomAccessRangeBase<T, true>:
detail::IsRandomAccessRangeCore<T>::Type {};
} }
template<typename T, bool = detail::IsRangeTest<T>::value> template<typename T> static constexpr bool IsRandomAccessRange
struct IsRandomAccessRange: False {}; = detail::IsRandomAccessRangeBase<T>::value;
template<typename T>
struct IsRandomAccessRange<T, true>:
detail::IsRandomAccessRangeBase<T>::Type {};
// is finite random access range // is finite random access range
namespace detail { namespace detail {
template<typename T, bool = IsConvertible< template<typename T, bool = IsConvertible<
RangeCategory<T>, FiniteRandomAccessRangeTag RangeCategory<T>, FiniteRandomAccessRangeTag
>::value> struct IsFiniteRandomAccessRangeBase: False {}; >::value> struct IsFiniteRandomAccessRangeCore: False {};
template<typename T> template<typename T>
struct IsFiniteRandomAccessRangeBase<T, true>: True {}; struct IsFiniteRandomAccessRangeCore<T, true>: True {};
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsFiniteRandomAccessRangeBase: False {};
template<typename T>
struct IsFiniteRandomAccessRangeBase<T, true>:
detail::IsFiniteRandomAccessRangeCore<T>::Type {};
} }
template<typename T, bool = detail::IsRangeTest<T>::value> template<typename T> static constexpr bool IsFiniteRandomAccessRange
struct IsFiniteRandomAccessRange: False {}; = detail::IsFiniteRandomAccessRangeBase<T>::value;
template<typename T>
struct IsFiniteRandomAccessRange<T, true>:
detail::IsFiniteRandomAccessRangeBase<T>::Type {};
// is infinite random access range // is infinite random access range
template<typename T> template<typename T> static constexpr bool IsInfiniteRandomAccessRange
struct IsInfiniteRandomAccessRange: IntegralConstant<bool, = IsRandomAccessRange<T> && !IsFiniteRandomAccessRange<T>;
(IsRandomAccessRange<T>::value && !IsFiniteRandomAccessRange<T>::value)
> {};
// is contiguous range // is contiguous range
namespace detail { namespace detail {
template<typename T, bool = IsConvertible< template<typename T, bool = IsConvertible<
RangeCategory<T>, ContiguousRangeTag RangeCategory<T>, ContiguousRangeTag
>::value> struct IsContiguousRangeBase: False {}; >::value> struct IsContiguousRangeCore: False {};
template<typename T> template<typename T>
struct IsContiguousRangeBase<T, true>: True {}; struct IsContiguousRangeCore<T, true>: True {};
template<typename T, bool = detail::IsRangeTest<T>::value>
struct IsContiguousRangeBase: False {};
template<typename T>
struct IsContiguousRangeBase<T, true>:
detail::IsContiguousRangeCore<T>::Type {};
} }
template<typename T, bool = detail::IsRangeTest<T>::value> template<typename T> static constexpr bool IsContiguousRange
struct IsContiguousRange: False {}; = detail::IsContiguousRangeBase<T>::value;
template<typename T>
struct IsContiguousRange<T, true>:
detail::IsContiguousRangeBase<T>::Type {};
// is output range // is output range
@ -191,18 +207,28 @@ namespace detail {
template<typename U> static int test(...); template<typename U> static int test(...);
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char)); static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char));
}; };
}
template<typename T, bool = (IsConvertible< template<typename T, bool = (IsConvertible<
RangeCategory<T>, OutputRangeTag RangeCategory<T>, OutputRangeTag
>::value || (IsInputRange<T>::value && >::value || (IsInputRange<T> &&
(detail::OutputRangeTest<T, const RangeValue<T> &>::value || (detail::OutputRangeTest<T, const RangeValue<T> &>::value ||
detail::OutputRangeTest<T, RangeValue<T> &&>::value || detail::OutputRangeTest<T, RangeValue<T> &&>::value ||
detail::OutputRangeTest<T, RangeValue<T> >::value) detail::OutputRangeTest<T, RangeValue<T> >::value)
))> struct IsOutputRange: False {}; ))> struct IsOutputRangeCore: False {};
template<typename T> 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 { namespace detail {
// range iterator // range iterator
@ -236,7 +262,7 @@ namespace detail {
template<typename T> struct HalfRange; template<typename T> struct HalfRange;
namespace detail { namespace detail {
template<typename R, bool = IsBidirectionalRange<typename R::Range>::value> template<typename R, bool = IsBidirectionalRange<typename R::Range>>
struct RangeAdd; struct RangeAdd;
template<typename R> template<typename R>
@ -484,9 +510,8 @@ template<typename B, typename C, typename V, typename R = V &,
return (on - n); return (on - n);
} }
template<typename OR, template<typename OR, typename = EnableIf<IsOutputRange<OR>>>
typename = EnableIf<IsOutputRange<OR>::value> Size copy(OR &&orange, Size n = -1) {
> Size copy(OR &&orange, Size n = -1) {
B r(*((B *)this)); B r(*((B *)this));
Size on = n; Size on = n;
for (; n && !r.empty(); --n) { for (; n && !r.empty(); --n) {
@ -995,9 +1020,8 @@ public:
return ret; return ret;
} }
template<typename R, template<typename R, typename = EnableIf<IsOutputRange<R>>>
typename = EnableIf<IsOutputRange<R>::value Size copy(R &&orange, Size n = -1) {
>> Size copy(R &&orange, Size n = -1) {
Size c = size(); Size c = size();
if (n < c) c = n; if (n < c) c = n;
return orange.put_n(p_beg, c); return orange.put_n(p_beg, c);

View File

@ -75,8 +75,7 @@ namespace detail {
SetImpl(SetImpl &&m, const A &alloc): Base(move(m), alloc) {} SetImpl(SetImpl &&m, const A &alloc): Base(move(m), alloc) {}
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> SetImpl(R range, Size size = 0, const H &hf = H(), >> SetImpl(R range, Size size = 0, const H &hf = H(),
const C &eqf = C(), const A &alloc = A() const C &eqf = C(), const A &alloc = A()
): Base(size ? size : detail::estimate_hrsize(range), ): Base(size ? size : detail::estimate_hrsize(range),
@ -116,8 +115,7 @@ namespace detail {
} }
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> SetImpl &operator=(R range) { >> SetImpl &operator=(R range) {
Base::assign_range(range); Base::assign_range(range);
return *this; return *this;

View File

@ -209,8 +209,7 @@ class StringBase {
template<typename R> template<typename R>
void ctor_from_range(R &range, EnableIf< void ctor_from_range(R &range, EnableIf<
IsFiniteRandomAccessRange<R>::value && IsFiniteRandomAccessRange<R> && IsSame<T, RemoveCv<RangeValue<R>>>, bool
IsSame<T, RemoveCv<RangeValue<R>>>, bool
> = true) { > = true) {
if (range.empty()) return; if (range.empty()) return;
RangeSize<R> l = range.size(); RangeSize<R> l = range.size();
@ -222,8 +221,8 @@ class StringBase {
template<typename R> template<typename R>
void ctor_from_range(R &range, EnableIf< void ctor_from_range(R &range, EnableIf<
!IsFiniteRandomAccessRange<R>::value || !IsFiniteRandomAccessRange<R> || !IsSame<T, RemoveCv<RangeValue<R>>>,
!IsSame<T, RemoveCv<RangeValue<R>>>, bool bool
> = true) { > = true) {
if (range.empty()) return; if (range.empty()) return;
Size i = 0; Size i = 0;
@ -327,8 +326,7 @@ public:
> &a = A()): StringBase(ConstRange(v), a) {} > &a = A()): StringBase(ConstRange(v), a) {}
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> StringBase(R range, const A &a = A()): StringBase(a) { >> StringBase(R range, const A &a = A()): StringBase(a) {
ctor_from_range(range); ctor_from_range(range);
} }
@ -400,8 +398,7 @@ public:
} }
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> StringBase &operator=(const R &r) { >> StringBase &operator=(const R &r) {
clear(); clear();
ctor_from_range(r); ctor_from_range(r);
@ -503,7 +500,7 @@ public:
} }
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> &&
IsConvertible<RangeReference<R>, Value>::value && IsConvertible<RangeReference<R>, Value>::value &&
!IsConvertible<R, ConstRange>::value !IsConvertible<R, ConstRange>::value
>> StringBase &append(R range) { >> StringBase &append(R range) {

View File

@ -35,7 +35,7 @@ class Vector {
template<typename R> template<typename R>
void ctor_from_range(R &range, EnableIf< void ctor_from_range(R &range, EnableIf<
IsFiniteRandomAccessRange<R>::value && IsPod<T> && IsFiniteRandomAccessRange<R> && IsPod<T> &&
IsSame<T, RemoveCv<RangeValue<R>>>, bool IsSame<T, RemoveCv<RangeValue<R>>>, bool
> = true) { > = true) {
RangeSize<R> l = range.size(); RangeSize<R> l = range.size();
@ -46,7 +46,7 @@ class Vector {
template<typename R> template<typename R>
void ctor_from_range(R &range, EnableIf< void ctor_from_range(R &range, EnableIf<
!IsFiniteRandomAccessRange<R>::value || !IsPod<T> || !IsFiniteRandomAccessRange<R> || !IsPod<T> ||
!IsSame<T, RemoveCv<RangeValue<R>>>, bool !IsSame<T, RemoveCv<RangeValue<R>>>, bool
> = true) { > = true) {
Size i = 0; Size i = 0;
@ -151,8 +151,7 @@ public:
Vector(ConstRange(v.begin(), v.size()), a) {} Vector(ConstRange(v.begin(), v.size()), a) {}
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> Vector(R range, const A &a = A()): Vector(a) { >> Vector(R range, const A &a = A()): Vector(a) {
ctor_from_range(range); ctor_from_range(range);
} }
@ -219,8 +218,7 @@ public:
} }
template<typename R, typename = EnableIf< template<typename R, typename = EnableIf<
IsInputRange<R>::value && IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsConvertible<RangeReference<R>, Value>::value
>> Vector &operator=(R range) { >> Vector &operator=(R range) {
clear(); clear();
ctor_from_range(range); ctor_from_range(range);