convert the remaining type_traits.hh checking traits to constexpr bools

master
Daniel Kolesa 2016-01-13 18:09:21 +00:00
parent a6744105dc
commit 818cbe376a
12 changed files with 164 additions and 166 deletions

View File

@ -736,9 +736,8 @@ namespace detail {
template<typename>
static Nat test(...);
static constexpr bool value = IsConvertible<
decltype(test<T>(nullptr)), R
>::value;
static constexpr bool value
= IsConvertible<decltype(test<T>(nullptr)), R>;
};
template<typename T>

View File

@ -56,8 +56,7 @@ public:
template<typename U>
HashRange(const HashRange<U> &v, EnableIf<
IsSame<RemoveCv<T>, RemoveCv<U>> &&
IsConvertible<U *, T *>::value, bool
IsSame<RemoveCv<T>, RemoveCv<U>> && IsConvertible<U *, T *>, bool
> = true): p_node((Chain *)v.p_node) {}
HashRange &operator=(const HashRange &v) {
@ -95,8 +94,7 @@ public:
template<typename U>
BucketRange(const BucketRange<U> &v, EnableIf<
IsSame<RemoveCv<T>, RemoveCv<U>> &&
IsConvertible<U *, T *>::value, bool
IsSame<RemoveCv<T>, RemoveCv<U>> && IsConvertible<U *, T *>, bool
> = true): p_node((Chain *)v.p_node), p_end((Chain *)v.p_end) {}
BucketRange &operator=(const BucketRange &v) {

View File

@ -185,7 +185,7 @@ namespace detail {
template<typename T, typename ...TT, typename U, typename ...UU>
struct TupleConvertibleBase<TupleTypes<T, TT...>, TupleTypes<U, UU...>>:
IntegralConstant<bool, IsConvertible<T, U>::value &&
IntegralConstant<bool, IsConvertible<T, U> &&
TupleConvertibleBase<TupleTypes<TT...>,
TupleTypes<UU...>>::value> {};

View File

@ -86,7 +86,7 @@ namespace detail {
KeysetImpl(KeysetImpl &&m, const A &alloc): Base(move(m), alloc) {}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, 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),
@ -126,7 +126,7 @@ namespace detail {
}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
>> KeysetImpl &operator=(R range) {
Base::assign_range(range);
return *this;

View File

@ -86,7 +86,7 @@ namespace detail {
MapImpl(MapImpl &&m, const A &alloc): Base(move(m), alloc) {}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, 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),
@ -126,7 +126,7 @@ namespace detail {
}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
>> MapImpl &operator=(R range) {
Base::assign_range(range);
return *this;

View File

@ -24,7 +24,7 @@ struct Nothing {
constexpr Nothing nothing = Nothing(0);
namespace detail {
template<typename T, bool = IsTriviallyDestructible<T>::value>
template<typename T, bool = IsTriviallyDestructible<T>>
class MaybeStorage {
protected:
using Value = T;
@ -101,7 +101,7 @@ public:
"Initialization of Maybe with Nothing is not allowed.");
static_assert(IsObject<T>,
"Initialization of Maybe with non-object type is not allowed.");
static_assert(IsDestructible<T>::value,
static_assert(IsDestructible<T>,
"Initialization of Maybe with a non-destructible object is not allowed.");
constexpr Maybe() {}
@ -219,7 +219,7 @@ public:
constexpr Value value_or(U &&v) const & {
static_assert(IsCopyConstructible<Value>,
"Maybe<T>::value_or: T must be copy constructible");
static_assert(IsConvertible<U, Value>::value,
static_assert(IsConvertible<U, Value>,
"Maybe<T>::value_or: U must be convertible to T");
return this->p_engaged ? this->p_value : Value(forward<U>(v));
}
@ -228,7 +228,7 @@ public:
Value value_or(U &&v) && {
static_assert(IsMoveConstructible<Value>,
"Maybe<T>::value_or: T must be copy constructible");
static_assert(IsConvertible<U, Value>::value,
static_assert(IsConvertible<U, Value>,
"Maybe<T>::value_or: U must be convertible to T");
return this->p_engaged ? move(this->p_value)
: Value(forward<U>(v));

View File

@ -262,9 +262,8 @@ public:
template<typename TT, typename DD>
Box(Box<TT, DD> &&u, EnableIf<!IsArray<TT>
&& IsConvertible<typename Box<TT, DD>::Pointer, Pointer>::value
&& IsConvertible<DD, D>::value
&& (!IsReference<D> || IsSame<D, DD>)
&& IsConvertible<typename Box<TT, DD>::Pointer, Pointer>
&& IsConvertible<DD, D> && (!IsReference<D> || IsSame<D, DD>)
> = Nat()): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
Box &operator=(Box &&u) {
@ -275,7 +274,7 @@ public:
template<typename TT, typename DD>
EnableIf<!IsArray<TT>
&& IsConvertible<typename Box<TT, DD>::Pointer, Pointer>::value
&& IsConvertible<typename Box<TT, DD>::Pointer, Pointer>
&& IsAssignable<D &, DD &&>,
Box &
> operator=(Box<TT, DD> &&u) {
@ -327,7 +326,8 @@ namespace detail {
template<typename T, typename U, bool = IsSame<
RemoveCv<PointerElement<T>>,
RemoveCv<PointerElement<U>>
>> struct SameOrLessCvQualifiedBase: IsConvertible<T, U> {};
>> struct SameOrLessCvQualifiedBase:
IntegralConstant<bool, IsConvertible<T, U>> {};
template<typename T, typename U>
struct SameOrLessCvQualifiedBase<T, U, false>: False {};
@ -392,8 +392,7 @@ public:
Box(Box<TT, DD> &&u, EnableIf<IsArray<TT>
&& detail::SameOrLessCvQualified<typename Box<TT, DD>::Pointer,
Pointer>::value
&& IsConvertible<DD, D>::value
&& (!IsReference<D> || IsSame<D, DD>)> = Nat()
&& IsConvertible<DD, D> && (!IsReference<D> || IsSame<D, DD>)> = Nat()
): p_stor(u.release(), forward<DD>(u.get_deleter())) {}
Box &operator=(Box &&u) {
@ -1067,7 +1066,7 @@ namespace detail {
template<typename T, typename A, bool = HasAllocatorType<T>::value>
struct UsesAllocatorBase: IntegralConstant<bool,
IsConvertible<A, typename T::Allocator>::value
IsConvertible<A, typename T::Allocator>
> {};
template<typename T, typename A>

View File

@ -71,9 +71,8 @@ namespace detail {
// is input range
namespace detail {
template<typename T, bool = IsConvertible<
RangeCategory<T>, InputRangeTag
>::value> struct IsInputRangeCore: False {};
template<typename T, bool = IsConvertible<RangeCategory<T>, InputRangeTag>>
struct IsInputRangeCore: False {};
template<typename T>
struct IsInputRangeCore<T, true>: True {};
@ -91,9 +90,8 @@ static constexpr bool IsInputRange = detail::IsInputRangeBase<T>::value;
// is forward range
namespace detail {
template<typename T, bool = IsConvertible<
RangeCategory<T>, ForwardRangeTag
>::value> struct IsForwardRangeCore: False {};
template<typename T, bool = IsConvertible<RangeCategory<T>, ForwardRangeTag>>
struct IsForwardRangeCore: False {};
template<typename T>
struct IsForwardRangeCore<T, true>: True {};
@ -113,7 +111,7 @@ static constexpr bool IsForwardRange = detail::IsForwardRangeBase<T>::value;
namespace detail {
template<typename T, bool = IsConvertible<
RangeCategory<T>, BidirectionalRangeTag
>::value> struct IsBidirectionalRangeCore: False {};
>> struct IsBidirectionalRangeCore: False {};
template<typename T>
struct IsBidirectionalRangeCore<T, true>: True {};
@ -134,7 +132,7 @@ template<typename T> static constexpr bool IsBidirectionalRange
namespace detail {
template<typename T, bool = IsConvertible<
RangeCategory<T>, RandomAccessRangeTag
>::value> struct IsRandomAccessRangeCore: False {};
>> struct IsRandomAccessRangeCore: False {};
template<typename T>
struct IsRandomAccessRangeCore<T, true>: True {};
@ -155,7 +153,7 @@ template<typename T> static constexpr bool IsRandomAccessRange
namespace detail {
template<typename T, bool = IsConvertible<
RangeCategory<T>, FiniteRandomAccessRangeTag
>::value> struct IsFiniteRandomAccessRangeCore: False {};
>> struct IsFiniteRandomAccessRangeCore: False {};
template<typename T>
struct IsFiniteRandomAccessRangeCore<T, true>: True {};
@ -181,7 +179,7 @@ template<typename T> static constexpr bool IsInfiniteRandomAccessRange
namespace detail {
template<typename T, bool = IsConvertible<
RangeCategory<T>, ContiguousRangeTag
>::value> struct IsContiguousRangeCore: False {};
>> struct IsContiguousRangeCore: False {};
template<typename T>
struct IsContiguousRangeCore<T, true>: True {};
@ -210,7 +208,7 @@ namespace detail {
template<typename T, bool = (IsConvertible<
RangeCategory<T>, OutputRangeTag
>::value || (IsInputRange<T> &&
> || (IsInputRange<T> &&
(detail::OutputRangeTest<T, const RangeValue<T> &>::value ||
detail::OutputRangeTest<T, RangeValue<T> &&>::value ||
detail::OutputRangeTest<T, RangeValue<T> >::value)
@ -304,9 +302,8 @@ public:
RangeHalf() = delete;
RangeHalf(const T &range): p_range(range) {}
template<typename U, typename = EnableIf<
IsConvertible<U, T>::value
>> RangeHalf(const RangeHalf<U> &half): p_range(half.p_range) {}
template<typename U, typename = EnableIf<IsConvertible<U, T>>>
RangeHalf(const RangeHalf<U> &half): p_range(half.p_range) {}
RangeHalf(const RangeHalf &half): p_range(half.p_range) {}
RangeHalf(RangeHalf &&half): p_range(move(half.p_range)) {}
@ -899,16 +896,13 @@ public:
template<typename U>
PointerRange(T *beg, U end, EnableIf<
(IsPointer<U> || IsNullPointer<U>) &&
IsConvertible<U, T *>::value, Nat
(IsPointer<U> || IsNullPointer<U>) && IsConvertible<U, T *>, Nat
> = Nat()): p_beg(beg), p_end(end) {}
PointerRange(T *beg, Size n): p_beg(beg), p_end(beg + n) {}
template<typename U, typename = EnableIf<
IsConvertible<U *, T *>::value
>> PointerRange(const PointerRange<U> &v):
p_beg(&v[0]), p_end(&v[v.size()]) {}
template<typename U, typename = EnableIf<IsConvertible<U *, T *>>>
PointerRange(const PointerRange<U> &v): p_beg(&v[0]), p_end(&v[v.size()]) {}
PointerRange &operator=(const PointerRange &v) {
p_beg = v.p_beg;
@ -1051,8 +1045,7 @@ namespace detail {
template<typename T, typename U>
PointerRange<T> iter(T *a, U b, EnableIf<
(IsPointer<U> || IsNullPointer<U>) &&
IsConvertible<U, T *>::value, detail::PtrNat
(IsPointer<U> || IsNullPointer<U>) && IsConvertible<U, T *>, detail::PtrNat
> = detail::PtrNat()) {
return PointerRange<T>(a, b);
}

View File

@ -75,7 +75,7 @@ namespace detail {
SetImpl(SetImpl &&m, const A &alloc): Base(move(m), alloc) {}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, 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),
@ -115,7 +115,7 @@ namespace detail {
}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
>> SetImpl &operator=(R range) {
Base::assign_range(range);
return *this;

View File

@ -32,35 +32,30 @@ public:
template<typename U>
CharRangeBase(T *beg, U end, EnableIf<
(IsPointer<U> || IsNullPointer<U>) &&
IsConvertible<U, T *>::value, Nat
(IsPointer<U> || IsNullPointer<U>) && IsConvertible<U, T *>, Nat
> = Nat()): p_beg(beg), p_end(end) {}
CharRangeBase(T *beg, Size n): p_beg(beg), p_end(beg + n) {}
/* TODO: traits for utf-16/utf-32 string lengths, for now assume char */
template<typename U>
CharRangeBase(U beg, EnableIf<
IsConvertible<U, T *>::value && !IsArray<U>, Nat
> = Nat()): p_beg(beg), p_end((T *)beg + (beg ? strlen(beg) : 0)) {}
CharRangeBase(U beg, EnableIf<IsConvertible<U, T *> && !IsArray<U>, Nat>
= Nat()): p_beg(beg), p_end((T *)beg + (beg ? strlen(beg) : 0)) {}
CharRangeBase(Nullptr): p_beg(nullptr), p_end(nullptr) {}
template<typename U, Size N>
CharRangeBase(U (&beg)[N], EnableIf<
IsConvertible<U *, T *>::value, Nat
> = Nat()): p_beg(beg),
p_end(beg + N - (beg[N - 1] == '\0')) {}
CharRangeBase(U (&beg)[N], EnableIf<IsConvertible<U *, T *>, Nat> = Nat()):
p_beg(beg), p_end(beg + N - (beg[N - 1] == '\0')) {}
template<typename U, typename A>
CharRangeBase(const StringBase<U, A> &s, EnableIf<
IsConvertible<U *, T *>::value, Nat
IsConvertible<U *, T *>, Nat
> = Nat()): p_beg(s.data()),
p_end(s.data() + s.size()) {}
template<typename U, typename = EnableIf<
IsConvertible<U *, T *>::value
>> CharRangeBase(const CharRangeBase<U> &v):
template<typename U, typename = EnableIf<IsConvertible<U *, T *>>>
CharRangeBase(const CharRangeBase<U> &v):
p_beg(&v[0]), p_end(&v[v.size()]) {}
CharRangeBase &operator=(const CharRangeBase &v) {
@ -317,16 +312,16 @@ public:
template<typename U>
StringBase(U v, const EnableIf<
IsConvertible<U, const Value *>::value && !IsArray<U>, A
IsConvertible<U, const Value *> && !IsArray<U>, A
> &a = A()): StringBase(ConstRange(v), a) {}
template<typename U, Size N>
StringBase(U (&v)[N], const EnableIf<
IsConvertible<U *, const Value *>::value, A
IsConvertible<U *, const Value *>, A
> &a = A()): StringBase(ConstRange(v), a) {}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
>> StringBase(R range, const A &a = A()): StringBase(a) {
ctor_from_range(range);
}
@ -384,21 +379,19 @@ public:
}
template<typename U>
EnableIf<
IsConvertible<U, const Value *>::value && !IsArray<U>, StringBase &
> operator=(U v) {
EnableIf<IsConvertible<U, const Value *> && !IsArray<U>, StringBase &>
operator=(U v) {
return operator=(ConstRange(v));
}
template<typename U, Size N>
EnableIf<
IsConvertible<U *, const Value *>::value, StringBase &
> operator=(U (&v)[N]) {
EnableIf<IsConvertible<U *, const Value *>, StringBase &>
operator=(U (&v)[N]) {
return operator=(ConstRange(v));
}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
>> StringBase &operator=(const R &r) {
clear();
ctor_from_range(r);
@ -500,9 +493,8 @@ public:
}
template<typename R, typename = EnableIf<
IsInputRange<R> &&
IsConvertible<RangeReference<R>, Value>::value &&
!IsConvertible<R, ConstRange>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value> &&
!IsConvertible<R, ConstRange>
>> StringBase &append(R range) {
Size nadd = 0;
for (; !range.empty(); range.pop_front()) {
@ -578,8 +570,8 @@ inline namespace literals { inline namespace string_literals {
} }
namespace detail {
template<typename T, bool = IsConvertible<T, ConstCharRange>::value,
bool = IsConvertible<T, char>::value>
template<typename T, bool = IsConvertible<T, ConstCharRange>,
bool = IsConvertible<T, char>>
struct ConcatPut;
template<typename T, bool B>

View File

@ -582,108 +582,113 @@ namespace detail {
: DtibleImpl<T, IsReference<T>> {};
template<typename T> struct DtibleFalse<T, true>: False {};
template<typename T>
struct IsDestructibleBase: detail::DtibleFalse<T, IsFunction<T>> {};
template<typename T> struct IsDestructibleBase<T[]>: False {};
template< > struct IsDestructibleBase<void>: False {};
} /* namespace detail */
template<typename T>
struct IsDestructible: detail::DtibleFalse<T, IsFunction<T>> {};
template<typename T> struct IsDestructible<T[]>: False {};
template< > struct IsDestructible<void>: False {};
static constexpr bool IsDestructible = detail::IsDestructibleBase<T>::value;
/* is trivially constructible */
namespace detail {
template<typename T, typename ...A>
struct IsTriviallyConstructibleBase: False {};
template<typename T>
struct IsTriviallyConstructibleBase<T>: IntegralConstant<bool,
__has_trivial_constructor(T)
> {};
template<typename T>
struct IsTriviallyConstructibleBase<T, T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyConstructibleBase<T, const T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyConstructibleBase<T, T &&>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
} /* namespace detail */
template<typename T, typename ...A>
struct IsTriviallyConstructible: False {};
template<typename T>
struct IsTriviallyConstructible<T>: IntegralConstant<bool,
__has_trivial_constructor(T)
> {};
template<typename T>
struct IsTriviallyConstructible<T, T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyConstructible<T, const T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyConstructible<T, T &&>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
static constexpr bool IsTriviallyConstructible
= detail::IsTriviallyConstructibleBase<T, A...>::value;
/* is trivially default constructible */
template<typename T>
struct IsTriviallyDefaultConstructible: IsTriviallyConstructible<T> {};
template<typename T> static constexpr bool IsTriviallyDefaultConstructible
= IsTriviallyConstructible<T>;
/* is trivially copy constructible */
template<typename T>
struct IsTriviallyCopyConstructible: IsTriviallyConstructible<T,
AddLvalueReference<const T>
> {};
template<typename T> static constexpr bool IsTriviallyCopyConstructible
= IsTriviallyConstructible<T, AddLvalueReference<const T>>;
/* is trivially move constructible */
template<typename T>
struct IsTriviallyMoveConstructible: IsTriviallyConstructible<T,
AddRvalueReference<T>
> {};
template<typename T> static constexpr bool IsTriviallyMoveConstructible
= IsTriviallyConstructible<T, AddRvalueReference<T>>;
/* is trivially assignable */
namespace detail {
template<typename T, typename ...A>
struct IsTriviallyAssignableBase: False {};
template<typename T>
struct IsTriviallyAssignableBase<T>: IntegralConstant<bool,
__has_trivial_assign(T)
> {};
template<typename T>
struct IsTriviallyAssignableBase<T, T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyAssignableBase<T, const T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyAssignableBase<T, T &&>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
} /* namespace detail */
template<typename T, typename ...A>
struct IsTriviallyAssignable: False {};
template<typename T>
struct IsTriviallyAssignable<T>: IntegralConstant<bool,
__has_trivial_assign(T)
> {};
template<typename T>
struct IsTriviallyAssignable<T, T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyAssignable<T, const T &>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
template<typename T>
struct IsTriviallyAssignable<T, T &&>: IntegralConstant<bool,
__has_trivial_copy(T)
> {};
static constexpr bool IsTriviallyAssignable
= detail::IsTriviallyAssignableBase<T>::value;
/* is trivially copy assignable */
template<typename T>
struct IsTriviallyCopyAssignable: IsTriviallyAssignable<T,
AddLvalueReference<const T>
> {};
template<typename T> static constexpr bool IsTriviallyCopyAssignable
= IsTriviallyAssignable<T, AddLvalueReference<const T>>;
/* is trivially move assignable */
template<typename T>
struct IsTriviallyMoveAssignable: IsTriviallyAssignable<T,
AddRvalueReference<T>
> {};
template<typename T> static constexpr bool IsTriviallyMoveAssignable
= IsTriviallyAssignable<T, AddRvalueReference<T>>;
/* is trivially destructible */
template<typename T>
struct IsTriviallyDestructible: IntegralConstant<bool,
__has_trivial_destructor(T)
> {};
static constexpr bool IsTriviallyDestructible = __has_trivial_destructor(T);
/* is base of */
template<typename B, typename D>
struct IsBaseOf: IntegralConstant<bool, __is_base_of(B, D)> {};
static constexpr bool IsBaseOf = __is_base_of(B, D);
/* is convertible */
@ -708,35 +713,47 @@ namespace detail {
};
}
template<typename F, typename T>
struct IsConvertible: detail::IsConvertibleBase<F, T>::Type {};
template<typename F, typename T> static constexpr bool IsConvertible
= detail::IsConvertibleBase<F, T>::Type::value;
/* extent */
namespace detail {
template<typename T, uint I>
struct ExtentBase: IntegralConstant<Size, 0> {};
template<typename T>
struct ExtentBase<T[], 0>: IntegralConstant<Size, 0> {};
template<typename T, uint I>
struct ExtentBase<T[], I>:
IntegralConstant<Size, detail::ExtentBase<T, I - 1>::value> {};
template<typename T, Size N>
struct ExtentBase<T[N], 0>: IntegralConstant<Size, N> {};
template<typename T, Size N, uint I>
struct ExtentBase<T[N], I>:
IntegralConstant<Size, detail::ExtentBase<T, I - 1>::value> {};
} /* namespace detail */
template<typename T, uint I = 0>
struct Extent: IntegralConstant<Size, 0> {};
template<typename T>
struct Extent<T[], 0>: IntegralConstant<Size, 0> {};
template<typename T, uint I>
struct Extent<T[], I>: IntegralConstant<Size, Extent<T, I - 1>::value> {};
template<typename T, Size N>
struct Extent<T[N], 0>: IntegralConstant<Size, N> {};
template<typename T, Size N, uint I>
struct Extent<T[N], I>: IntegralConstant<Size, Extent<T, I - 1>::value> {};
static constexpr Size Extent = detail::ExtentBase<T, I>::value;
/* rank */
template<typename T> struct Rank: IntegralConstant<Size, 0> {};
namespace detail {
template<typename T> struct RankBase: IntegralConstant<Size, 0> {};
template<typename T> struct RankBase<T[]>:
IntegralConstant<Size, detail::RankBase<T>::value + 1> {};
template<typename T, Size N> struct RankBase<T[N]>:
IntegralConstant<Size, detail::RankBase<T>::value + 1> {};
}
template<typename T>
struct Rank<T[]>: IntegralConstant<Size, Rank<T>::value + 1> {};
template<typename T, Size N>
struct Rank<T[N]>: IntegralConstant<Size, Rank<T>::value + 1> {};
static constexpr Size Rank = detail::RankBase<T>::value;
/* remove const, volatile, cv */

View File

@ -151,7 +151,7 @@ public:
Vector(ConstRange(v.begin(), v.size()), a) {}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
>> Vector(R range, const A &a = A()): Vector(a) {
ctor_from_range(range);
}
@ -218,7 +218,7 @@ public:
}
template<typename R, typename = EnableIf<
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>::value
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
>> Vector &operator=(R range) {
clear();
ctor_from_range(range);