add lots of new traits
parent
fff049d6c7
commit
c388e8c09a
19
README.md
19
README.md
|
@ -2,3 +2,22 @@
|
|||
|
||||
OctaSTD is a collection of C++ utilities to aid the upcoming OctaForge C++
|
||||
API. It provides containers (dynamic arrays etc) as well as other utilities.
|
||||
|
||||
It utilizes C++11. It also implements equivalents of certain C++14 library
|
||||
features that are possible to implement with the C++11 language. It does not
|
||||
go beyond C++11 level when it comes to core language features.
|
||||
|
||||
## Supported compilers
|
||||
|
||||
Compiler | Version
|
||||
-------- | -------
|
||||
gcc/g++ | 4.8+
|
||||
clang | 3.4+
|
||||
MSVC++ | 2015+
|
||||
|
||||
Other C++11 compliant compilers might work as well. OctaSTD does not utilize
|
||||
compiler specific extensions except certain builtin type traits - to implement
|
||||
traits that are not normally possible to implement without compiler support.
|
||||
|
||||
OctaSTD does not provide fallbacks for those traits. The compiler is expected
|
||||
to support these builtins. So far the 3 above-mentioned compilers support them.
|
||||
|
|
513
octa/traits.h
513
octa/traits.h
|
@ -19,24 +19,13 @@
|
|||
*/
|
||||
|
||||
namespace octa {
|
||||
/* removers */
|
||||
|
||||
template<typename T> struct RemoveConst { typedef T type; };
|
||||
template<typename T> struct RemoveConst<const T> { typedef T type; };
|
||||
|
||||
template<typename T> struct RemoveVolatile { typedef T type; };
|
||||
template<typename T> struct RemoveVolatile<volatile T> { typedef T type; };
|
||||
|
||||
template<typename T>
|
||||
struct RemoveConstVolatile {
|
||||
typedef typename RemoveVolatile<typename RemoveConst<T>::type>::type type;
|
||||
};
|
||||
template<typename> struct RemoveConstVolatile;
|
||||
|
||||
/* integral constant */
|
||||
|
||||
template<typename T, T val>
|
||||
struct IntegralConstant {
|
||||
static constexpr const T value = val;
|
||||
static constexpr T value = val;
|
||||
|
||||
typedef T value_type;
|
||||
typedef IntegralConstant<T, val> type;
|
||||
|
@ -48,7 +37,7 @@ namespace octa {
|
|||
typedef IntegralConstant<bool, true> true_t;
|
||||
typedef IntegralConstant<bool, false> false_t;
|
||||
|
||||
template<typename T, T val> constexpr const T IntegralConstant<T, val>::value;
|
||||
template<typename T, T val> constexpr T IntegralConstant<T, val>::value;
|
||||
|
||||
/* is void */
|
||||
|
||||
|
@ -179,15 +168,11 @@ namespace octa {
|
|||
!IsFundamental<T>::value
|
||||
> {};
|
||||
|
||||
/* is pointer to member function */
|
||||
|
||||
template<typename> struct IsMemberFunctionPointer: true_t {};
|
||||
|
||||
/* is pointer to member */
|
||||
|
||||
template<typename> struct IsMemberPointerBase: false_t {};
|
||||
template<typename T, typename U>
|
||||
struct IsMemberPointerBase<T U::*>: true_t {};
|
||||
struct IsMemberPointerBase<T U::*>: true_t {};
|
||||
|
||||
template<typename T>
|
||||
struct IsMemberPointer: IsMemberPointerBase<
|
||||
|
@ -196,10 +181,28 @@ namespace octa {
|
|||
|
||||
/* is pointer to member object */
|
||||
|
||||
template<typename T> struct IsMemberObjectPointer: IntegralConstant<bool,
|
||||
(IsMemberPointer<T>::value && !IsMemberFunctionPointer<T>::value)
|
||||
template<typename> struct IsMemberObjectPointerBase: false_t {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct IsMemberObjectPointerBase<T U::*>: IntegralConstant<bool,
|
||||
!IsFunction<T>::value
|
||||
> {};
|
||||
|
||||
template<typename T> struct IsMemberObjectPointer:
|
||||
IsMemberObjectPointerBase<typename RemoveConstVolatile<T>::type> {};
|
||||
|
||||
/* is pointer to member function */
|
||||
|
||||
template<typename> struct IsMemberFunctionPointerBase: false_t {};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct IsMemberFunctionPointerBase<T U::*>: IntegralConstant<bool,
|
||||
IsFunction<T>::value
|
||||
> {};
|
||||
|
||||
template<typename T> struct IsMemberFunctionPointer:
|
||||
IsMemberFunctionPointerBase<typename RemoveConstVolatile<T>::type> {};
|
||||
|
||||
/* is reference */
|
||||
|
||||
template<typename T> struct IsReference: IntegralConstant<bool,
|
||||
|
@ -270,6 +273,208 @@ namespace octa {
|
|||
|| IsStandardLayout<T>::value
|
||||
> {};
|
||||
|
||||
/* is trivially copyable */
|
||||
|
||||
template<typename T>
|
||||
struct IsTriviallyCopyable: IntegralConstant<bool,
|
||||
IsScalar<typename RemoveAllExtents<T>::type>::value
|
||||
> {};
|
||||
|
||||
/* is trivial */
|
||||
|
||||
template<typename> struct IsTriviallyDefaultConstructible;
|
||||
|
||||
template<typename T>
|
||||
struct IsTrivial: IntegralConstant<bool,
|
||||
(IsTriviallyCopyable<T>::value && IsTriviallyDefaultConstructible<T>::value)
|
||||
> {};
|
||||
|
||||
/* has virtual destructor */
|
||||
|
||||
template<typename T>
|
||||
struct HasVirtualDestructor: IntegralConstant<bool, __has_virtual_destructor(T)> {};
|
||||
|
||||
/* is trivially constructible */
|
||||
|
||||
template<typename T, typename ...A>
|
||||
struct IsTriviallyConstructible: false_t {};
|
||||
|
||||
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)
|
||||
> {};
|
||||
|
||||
/* is trivially default constructible */
|
||||
|
||||
template<typename T>
|
||||
struct IsTriviallyDefaultConstructible: IsTriviallyConstructible<T> {};
|
||||
|
||||
/* is trivially copy constructible */
|
||||
|
||||
template<typename> struct AddLvalueReference;
|
||||
|
||||
template<typename T>
|
||||
struct IsTriviallyCopyConstructible: IsTriviallyConstructible<T,
|
||||
typename AddLvalueReference<const T>::type
|
||||
> {};
|
||||
|
||||
/* is trivially move constructible */
|
||||
|
||||
template<typename T>
|
||||
struct IsTriviallyMoveConstructible: IsTriviallyConstructible<T,
|
||||
typename internal::AddRvalueReference<T>::type
|
||||
> {};
|
||||
|
||||
/* is trivially assignable */
|
||||
|
||||
template<typename T, typename ...A>
|
||||
struct IsTriviallyAssignable: false_t {};
|
||||
|
||||
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)
|
||||
> {};
|
||||
|
||||
/* is trivially copy assignable */
|
||||
|
||||
template<typename> struct AddLvalueReference;
|
||||
|
||||
template<typename T>
|
||||
struct IsTriviallyCopyAssignable: IsTriviallyAssignable<T,
|
||||
typename AddLvalueReference<const T>::type
|
||||
> {};
|
||||
|
||||
/* is trivially move assignable */
|
||||
|
||||
template<typename T>
|
||||
struct IsTriviallyMoveAssignable: IsTriviallyAssignable<T,
|
||||
typename internal::AddRvalueReference<T>::type
|
||||
> {};
|
||||
|
||||
/* is trivially destructible */
|
||||
|
||||
template<typename T>
|
||||
struct IsTriviallyDestructible: IntegralConstant<bool,
|
||||
__has_trivial_destructor(T)
|
||||
> {};
|
||||
|
||||
/* is nothrow constructible */
|
||||
|
||||
template<typename T, typename ...A>
|
||||
struct IsNothrowConstructible: false_t {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowConstructible<T>: IntegralConstant<bool,
|
||||
__has_nothrow_constructor(T)
|
||||
> {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowConstructible<T, T &>: IntegralConstant<bool,
|
||||
__has_nothrow_copy(T)
|
||||
> {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowConstructible<T, const T &>: IntegralConstant<bool,
|
||||
__has_nothrow_copy(T)
|
||||
> {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowConstructible<T, T &&>: IntegralConstant<bool,
|
||||
__has_nothrow_copy(T)
|
||||
> {};
|
||||
|
||||
/* is nothrow default constructible */
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowDefaultConstructible: IsNothrowConstructible<T> {};
|
||||
|
||||
/* is nothrow copy constructible */
|
||||
|
||||
template<typename> struct AddLvalueReference;
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowCopyConstructible: IsNothrowConstructible<T,
|
||||
typename AddLvalueReference<const T>::type
|
||||
> {};
|
||||
|
||||
/* is nothrow move constructible */
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowMoveConstructible: IsNothrowConstructible<T,
|
||||
typename internal::AddRvalueReference<T>::type
|
||||
> {};
|
||||
|
||||
/* is nothrow assignable */
|
||||
|
||||
template<typename T, typename ...A>
|
||||
struct IsNothrowAssignable: false_t {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowAssignable<T>: IntegralConstant<bool,
|
||||
__has_nothrow_assign(T)
|
||||
> {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowAssignable<T, T &>: IntegralConstant<bool,
|
||||
__has_nothrow_copy(T)
|
||||
> {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowAssignable<T, const T &>: IntegralConstant<bool,
|
||||
__has_nothrow_copy(T)
|
||||
> {};
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowAssignable<T, T &&>: IntegralConstant<bool,
|
||||
__has_nothrow_copy(T)
|
||||
> {};
|
||||
|
||||
/* is nothrow copy assignable */
|
||||
|
||||
template<typename> struct AddLvalueReference;
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowCopyAssignable: IsNothrowAssignable<T,
|
||||
typename AddLvalueReference<const T>::type
|
||||
> {};
|
||||
|
||||
/* is nothrow move assignable */
|
||||
|
||||
template<typename T>
|
||||
struct IsNothrowMoveAssignable: IsNothrowAssignable<T,
|
||||
typename internal::AddRvalueReference<T>::type
|
||||
> {};
|
||||
|
||||
/* is base of */
|
||||
|
||||
template<typename B, typename D>
|
||||
|
@ -330,6 +535,50 @@ namespace octa {
|
|||
template<typename T, size_t N>
|
||||
struct Rank<T[N]>: IntegralConstant<size_t, Rank<T>::value + 1> {};
|
||||
|
||||
/* remove const, volatile, cv */
|
||||
|
||||
template<typename T> struct RemoveConst { typedef T type; };
|
||||
template<typename T> struct RemoveConst<const T> { typedef T type; };
|
||||
|
||||
template<typename T> struct RemoveVolatile { typedef T type; };
|
||||
template<typename T> struct RemoveVolatile<volatile T> { typedef T type; };
|
||||
|
||||
template<typename T>
|
||||
struct RemoveConstVolatile {
|
||||
typedef typename RemoveVolatile<typename RemoveConst<T>::type>::type type;
|
||||
};
|
||||
|
||||
/* add const, volatile, cv */
|
||||
|
||||
template<typename T, bool = IsReference<T>::value
|
||||
|| IsFunction<T>::value || IsConst<T>::value>
|
||||
struct AddConstBase { typedef T type; };
|
||||
|
||||
template<typename T> struct AddConstBase<T, false> {
|
||||
typedef const T type;
|
||||
};
|
||||
|
||||
template<typename T> struct AddConst {
|
||||
typedef typename AddConstBase<T>::type type;
|
||||
};
|
||||
|
||||
template<typename T, bool = IsReference<T>::value
|
||||
|| IsFunction<T>::value || IsVolatile<T>::value>
|
||||
struct AddVolatileBase { typedef T type; };
|
||||
|
||||
template<typename T> struct AddVolatileBase<T, false> {
|
||||
typedef volatile T type;
|
||||
};
|
||||
|
||||
template<typename T> struct AddVolatile {
|
||||
typedef typename AddVolatileBase<T>::type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct AddConstVolatile {
|
||||
typedef typename AddConst<typename AddVolatile<T>::type>::type type;
|
||||
};
|
||||
|
||||
/* remove reference */
|
||||
|
||||
template<typename T> using RemoveReference = internal::RemoveReference<T>;
|
||||
|
@ -388,6 +637,147 @@ namespace octa {
|
|||
typedef typename RemoveAllExtents<T>::type type;
|
||||
};
|
||||
|
||||
/* make (un)signed
|
||||
*
|
||||
* this is bad, but i don't see any better way
|
||||
* shamelessly copied from graphitemaster @ neothyne
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template<typename T, typename U> struct TypeList {
|
||||
typedef T first;
|
||||
typedef U rest;
|
||||
};
|
||||
|
||||
/* not a type */
|
||||
struct NAT {
|
||||
NAT() = delete;
|
||||
NAT(const NAT &) = delete;
|
||||
NAT &operator=(const NAT &) = delete;
|
||||
~NAT() = delete;
|
||||
};
|
||||
|
||||
typedef TypeList<schar,
|
||||
TypeList<short,
|
||||
TypeList<int,
|
||||
TypeList<long,
|
||||
TypeList<llong, NAT>>>>> stypes;
|
||||
|
||||
typedef TypeList<uchar,
|
||||
TypeList<ushort,
|
||||
TypeList<uint,
|
||||
TypeList<ulong,
|
||||
TypeList<ullong, NAT>>>>> utypes;
|
||||
|
||||
template<typename T, size_t N, bool = (N <= sizeof(typename T::first))>
|
||||
struct TypeFindFirst;
|
||||
|
||||
template<typename T, typename U, size_t N>
|
||||
struct TypeFindFirst<TypeList<T, U>, N, true> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T, typename U, size_t N>
|
||||
struct TypeFindFirst<TypeList<T, U>, N, false> {
|
||||
typedef typename TypeFindFirst<U, N>::type type;
|
||||
};
|
||||
|
||||
template<typename T, typename U,
|
||||
bool = IsConst<typename RemoveReference<T>::type>::value,
|
||||
bool = IsVolatile<typename RemoveReference<T>::type>::value
|
||||
> struct ApplyConstVolatile {
|
||||
typedef U type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ApplyConstVolatile<T, U, true, false> { /* const */
|
||||
typedef const U type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ApplyConstVolatile<T, U, false, true> { /* volatile */
|
||||
typedef volatile U type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ApplyConstVolatile<T, U, true, true> { /* const volatile */
|
||||
typedef const volatile U type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ApplyConstVolatile<T &, U, true, false> { /* const */
|
||||
typedef const U &type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ApplyConstVolatile<T &, U, false, true> { /* volatile */
|
||||
typedef volatile U &type;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ApplyConstVolatile<T &, U, true, true> { /* const volatile */
|
||||
typedef const volatile U &type;
|
||||
};
|
||||
|
||||
template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value>
|
||||
struct MakeSigned {};
|
||||
|
||||
template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value>
|
||||
struct MakeUnsigned {};
|
||||
|
||||
template<typename T>
|
||||
struct MakeSigned<T, true> {
|
||||
typedef typename TypeFindFirst<stypes, sizeof(T)>::type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MakeUnsigned<T, true> {
|
||||
typedef typename TypeFindFirst<utypes, sizeof(T)>::type type;
|
||||
};
|
||||
|
||||
template<> struct MakeSigned<bool , true> {};
|
||||
template<> struct MakeSigned<schar , true> { typedef schar type; };
|
||||
template<> struct MakeSigned<uchar , true> { typedef schar type; };
|
||||
template<> struct MakeSigned<short , true> { typedef short type; };
|
||||
template<> struct MakeSigned<ushort, true> { typedef short type; };
|
||||
template<> struct MakeSigned<int , true> { typedef int type; };
|
||||
template<> struct MakeSigned<uint , true> { typedef int type; };
|
||||
template<> struct MakeSigned<long , true> { typedef long type; };
|
||||
template<> struct MakeSigned<ulong , true> { typedef long type; };
|
||||
template<> struct MakeSigned<llong , true> { typedef llong type; };
|
||||
template<> struct MakeSigned<ullong, true> { typedef llong type; };
|
||||
|
||||
template<> struct MakeUnsigned<bool , true> {};
|
||||
template<> struct MakeUnsigned<schar , true> { typedef uchar type; };
|
||||
template<> struct MakeUnsigned<uchar , true> { typedef uchar type; };
|
||||
template<> struct MakeUnsigned<short , true> { typedef ushort type; };
|
||||
template<> struct MakeUnsigned<ushort, true> { typedef ushort type; };
|
||||
template<> struct MakeUnsigned<int , true> { typedef uint type; };
|
||||
template<> struct MakeUnsigned<uint , true> { typedef uint type; };
|
||||
template<> struct MakeUnsigned<long , true> { typedef ulong type; };
|
||||
template<> struct MakeUnsigned<ulong , true> { typedef ulong type; };
|
||||
template<> struct MakeUnsigned<llong , true> { typedef ullong type; };
|
||||
template<> struct MakeUnsigned<ullong, true> { typedef ullong type; };
|
||||
}
|
||||
|
||||
template<typename T> struct MakeSigned {
|
||||
typedef typename internal::ApplyConstVolatile<T,
|
||||
typename internal::MakeSigned<
|
||||
typename RemoveConstVolatile<T>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<typename T> struct MakeUnsigned {
|
||||
typedef typename internal::ApplyConstVolatile<T,
|
||||
typename internal::MakeUnsigned<
|
||||
typename RemoveConstVolatile<T>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
/* common type */
|
||||
|
||||
/* conditional */
|
||||
|
||||
template<bool cond, typename T, typename U>
|
||||
|
@ -461,6 +851,87 @@ namespace octa {
|
|||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
/* common type */
|
||||
|
||||
template<typename ...T> struct CommonType;
|
||||
|
||||
template<typename T> struct CommonType<T> {
|
||||
typedef Decay<T> type;
|
||||
};
|
||||
|
||||
template<typename T, typename U> struct CommonType<T, U> {
|
||||
typedef Decay<decltype(true ? declval<T>() : declval<U>())> type;
|
||||
};
|
||||
|
||||
template<typename T, typename U, typename ...V>
|
||||
struct CommonType<T, U, V...> {
|
||||
typedef typename CommonType<typename CommonType<T, U>::type, V...>::type type;
|
||||
};
|
||||
|
||||
/* aligned storage */
|
||||
|
||||
namespace internal {
|
||||
template<size_t N> struct AlignedStorageTest {
|
||||
union type {
|
||||
uchar data[N];
|
||||
max_align_t align;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template<size_t N, size_t A
|
||||
= alignof(typename internal::AlignedStorageTest<N>::type)
|
||||
> struct AlignedStorage {
|
||||
struct type {
|
||||
alignas(A) uchar data[N];
|
||||
};
|
||||
};
|
||||
|
||||
/* aligned union */
|
||||
|
||||
namespace internal {
|
||||
template<size_t ...N> struct AlignMax;
|
||||
|
||||
template<size_t N> struct AlignMax<N> {
|
||||
static constexpr size_t value = N;
|
||||
};
|
||||
|
||||
template<size_t N1, size_t N2> struct AlignMax<N1, N2> {
|
||||
static constexpr size_t value = (N1 > N2) ? N1 : N2;
|
||||
};
|
||||
|
||||
template<size_t N1, size_t N2, size_t ...N>
|
||||
struct AlignMax<N1, N2, N...> {
|
||||
static constexpr size_t value
|
||||
= AlignMax<AlignMax<N1, N2>::value, N...>::value;
|
||||
};
|
||||
}
|
||||
|
||||
template<size_t N, typename ...T> struct AlignedUnion {
|
||||
static constexpr size_t alignment_value
|
||||
= internal::AlignMax<alignof(T)...>::value;
|
||||
|
||||
struct type {
|
||||
alignas(alignment_value) uchar data[internal::AlignMax<N,
|
||||
sizeof(T)...>::value];
|
||||
};
|
||||
};
|
||||
|
||||
/* underlying type */
|
||||
|
||||
template<typename T, bool = IsEnum<T>::value> struct UnderlyingTypeBase;
|
||||
|
||||
template<typename T> struct UnderlyingTypeBase<T, true> {
|
||||
typedef typename Conditional<IsSigned<T>::value,
|
||||
typename MakeSigned<T>::type,
|
||||
typename MakeUnsigned<T>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template<typename T> struct UnderlyingType {
|
||||
typedef typename UnderlyingTypeBase<T>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue