add lots of new traits

master
Daniel Kolesa 2015-04-23 18:47:33 +01:00
parent fff049d6c7
commit c388e8c09a
2 changed files with 511 additions and 21 deletions

View File

@ -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.

View File

@ -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