forked from OctaForge/libostd
sfinae friendly range traits + IsInputRange etc now works on arbitrary non-range types
parent
13e553f85c
commit
7cdac42c4a
101
octa/range.h
101
octa/range.h
|
@ -26,11 +26,19 @@ template<typename T> struct RangeHalf;
|
||||||
#define OCTA_RANGE_TRAIT(Name) \
|
#define OCTA_RANGE_TRAIT(Name) \
|
||||||
namespace detail { \
|
namespace detail { \
|
||||||
template<typename T> \
|
template<typename T> \
|
||||||
struct Range##Name##Base { \
|
struct Range##Name##Test { \
|
||||||
|
template<typename U> static char test(RemoveReference<typename U::Name> *); \
|
||||||
|
template<typename U> static int test(...); \
|
||||||
|
static constexpr bool value = (sizeof(test<T>(0)) == sizeof(char)); \
|
||||||
|
}; \
|
||||||
|
template<typename T, bool = Range##Name##Test<T>::value> \
|
||||||
|
struct Range##Name##Base {}; \
|
||||||
|
template<typename T> \
|
||||||
|
struct Range##Name##Base<T, true> { \
|
||||||
using Type = typename T::Name; \
|
using Type = typename T::Name; \
|
||||||
}; \
|
}; \
|
||||||
template<typename T> \
|
template<typename T> \
|
||||||
struct Range##Name##Base<RangeHalf<T>> { \
|
struct Range##Name##Base<RangeHalf<T>, true> { \
|
||||||
using Type = typename T::Name; \
|
using Type = typename T::Name; \
|
||||||
}; \
|
}; \
|
||||||
} \
|
} \
|
||||||
|
@ -45,50 +53,109 @@ OCTA_RANGE_TRAIT(Difference)
|
||||||
|
|
||||||
#undef OCTA_RANGE_TRAIT
|
#undef OCTA_RANGE_TRAIT
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template<typename T>
|
||||||
|
struct IsRangeTest {
|
||||||
|
template<typename U> static char test(typename U::Category *,
|
||||||
|
typename U::Size *,
|
||||||
|
typename U::Difference *,
|
||||||
|
typename U::Value *,
|
||||||
|
RemoveReference<
|
||||||
|
typename U::Reference
|
||||||
|
> *);
|
||||||
|
template<typename U> static int test(...);
|
||||||
|
static constexpr bool value
|
||||||
|
= (sizeof(test<T>(0, 0, 0, 0, 0)) == sizeof(char));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// is input range
|
// is input range
|
||||||
|
|
||||||
template<typename T, bool = octa::IsConvertible<
|
namespace detail {
|
||||||
|
template<typename T, bool = octa::IsConvertible<
|
||||||
RangeCategory<T>, InputRangeTag
|
RangeCategory<T>, InputRangeTag
|
||||||
>::value> struct IsInputRange: False {};
|
>::value> struct IsInputRangeBase: False {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsInputRangeBase<T, true>: True {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||||
|
struct IsInputRange: False {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IsInputRange<T, true>: True {};
|
struct IsInputRange<T, true>: octa::detail::IsInputRangeBase<T>::Type {};
|
||||||
|
|
||||||
// is forward range
|
// is forward range
|
||||||
|
|
||||||
template<typename T, bool = octa::IsConvertible<
|
namespace detail {
|
||||||
|
template<typename T, bool = octa::IsConvertible<
|
||||||
RangeCategory<T>, ForwardRangeTag
|
RangeCategory<T>, ForwardRangeTag
|
||||||
>::value> struct IsForwardRange: False {};
|
>::value> struct IsForwardRangeBase: False {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsForwardRangeBase<T, true>: True {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||||
|
struct IsForwardRange: False {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IsForwardRange<T, true>: True {};
|
struct IsForwardRange<T, true>: octa::detail::IsForwardRangeBase<T>::Type {};
|
||||||
|
|
||||||
// is bidirectional range
|
// is bidirectional range
|
||||||
|
|
||||||
template<typename T, bool = octa::IsConvertible<
|
namespace detail {
|
||||||
|
template<typename T, bool = octa::IsConvertible<
|
||||||
RangeCategory<T>, BidirectionalRangeTag
|
RangeCategory<T>, BidirectionalRangeTag
|
||||||
>::value> struct IsBidirectionalRange: False {};
|
>::value> struct IsBidirectionalRangeBase: False {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsBidirectionalRangeBase<T, true>: True {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||||
|
struct IsBidirectionalRange: False {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IsBidirectionalRange<T, true>: True {};
|
struct IsBidirectionalRange<T, true>:
|
||||||
|
octa::detail::IsBidirectionalRangeBase<T>::Type {};
|
||||||
|
|
||||||
// is random access range
|
// is random access range
|
||||||
|
|
||||||
template<typename T, bool = octa::IsConvertible<
|
namespace detail {
|
||||||
|
template<typename T, bool = octa::IsConvertible<
|
||||||
RangeCategory<T>, RandomAccessRangeTag
|
RangeCategory<T>, RandomAccessRangeTag
|
||||||
>::value> struct IsRandomAccessRange: False {};
|
>::value> struct IsRandomAccessRangeBase: False {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsRandomAccessRangeBase<T, true>: True {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||||
|
struct IsRandomAccessRange: False {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IsRandomAccessRange<T, true>: True {};
|
struct IsRandomAccessRange<T, true>:
|
||||||
|
octa::detail::IsRandomAccessRangeBase<T>::Type {};
|
||||||
|
|
||||||
// is finite random access range
|
// is finite random access range
|
||||||
|
|
||||||
template<typename T, bool = octa::IsConvertible<
|
namespace detail {
|
||||||
|
template<typename T, bool = octa::IsConvertible<
|
||||||
RangeCategory<T>, FiniteRandomAccessRangeTag
|
RangeCategory<T>, FiniteRandomAccessRangeTag
|
||||||
>::value> struct IsFiniteRandomAccessRange: False {};
|
>::value> struct IsFiniteRandomAccessRangeBase: False {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct IsFiniteRandomAccessRangeBase<T, true>: True {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, bool = octa::detail::IsRangeTest<T>::value>
|
||||||
|
struct IsFiniteRandomAccessRange: False {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct IsFiniteRandomAccessRange<T, true>: True {};
|
struct IsFiniteRandomAccessRange<T, true>:
|
||||||
|
octa::detail::IsFiniteRandomAccessRangeBase<T>::Type {};
|
||||||
|
|
||||||
// is infinite random access range
|
// is infinite random access range
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue