add all remaining traits + cleanup, remove namespace internal etc

master
Daniel Kolesa 2015-04-23 20:38:18 +01:00
parent a80f535b5d
commit 0c217e2128
3 changed files with 407 additions and 279 deletions

View File

@ -27,4 +27,10 @@ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.** SOFTWARE.**
Additionally some code from the libc++ project has been used as a reference;
libc++ is a part of the LLVM project.
Additional thanks to Dale Weiler aka graphitemaster (reference code in the
Neothyne project) and cppreference.com.

View File

@ -228,7 +228,7 @@ namespace octa {
}; };
template<typename T> template<typename T>
struct FunctorDataManager<T, typename enable_if<!FunctorInPlace<T> struct FunctorDataManager<T, typename EnableIf<!FunctorInPlace<T>
::value>::type> { ::value>::type> {
template<typename R, typename ...A> template<typename R, typename ...A>
static R call(const FunctorData &s, A ...args) { static R call(const FunctorData &s, A ...args) {

View File

@ -11,15 +11,17 @@
#include "octa/types.h" #include "octa/types.h"
#include "octa/utility.h" #include "octa/utility.h"
/* libc++ and cppreference.com occasionally used for reference */
/* missing:
*
* UnderlyingType<T>
*/
namespace octa { namespace octa {
template<typename> struct RemoveConstVolatile; /* forward declarations */
template<typename> struct RemoveCV;
template<typename> struct AddLvalueReference;
template<typename> struct AddConst;
template<typename> struct IsReference;
template<typename> struct RemoveAllExtents;
template<typename> struct IsTriviallyDefaultConstructible;
template<typename...> struct CommonType;
/* integral constant */ /* integral constant */
@ -41,52 +43,51 @@ namespace octa {
/* is void */ /* is void */
template<typename T> struct IsVoidBase : false_t {}; template<typename T> struct __OctaIsVoid : false_t {};
template< > struct IsVoidBase<void>: true_t {}; template< > struct __OctaIsVoid<void>: true_t {};
template<typename T> template<typename T>
struct IsVoid: IsVoidBase<typename RemoveConstVolatile<T>::type> {}; struct IsVoid: __OctaIsVoid<typename RemoveCV<T>::type> {};
/* is null pointer */ /* is null pointer */
template<typename> struct IsNullPointerBase : false_t {}; template<typename> struct __OctaIsNullPointer : false_t {};
template< > struct IsNullPointerBase<nullptr_t>: true_t {}; template< > struct __OctaIsNullPointer<nullptr_t>: true_t {};
template<typename T> template<typename T> struct IsNullPointer: __OctaIsNullPointer<
struct IsNullPointer: IsNullPointerBase< typename RemoveCV<T>::type
typename RemoveConstVolatile<T>::type
> {}; > {};
/* is integer */ /* is integer */
template<typename T> struct IsIntegralBase: false_t {}; template<typename T> struct __OctaIsIntegral: false_t {};
template<> struct IsIntegralBase<bool >: true_t {}; template<> struct __OctaIsIntegral<bool >: true_t {};
template<> struct IsIntegralBase<char >: true_t {}; template<> struct __OctaIsIntegral<char >: true_t {};
template<> struct IsIntegralBase<uchar >: true_t {}; template<> struct __OctaIsIntegral<uchar >: true_t {};
template<> struct IsIntegralBase<schar >: true_t {}; template<> struct __OctaIsIntegral<schar >: true_t {};
template<> struct IsIntegralBase<short >: true_t {}; template<> struct __OctaIsIntegral<short >: true_t {};
template<> struct IsIntegralBase<ushort>: true_t {}; template<> struct __OctaIsIntegral<ushort>: true_t {};
template<> struct IsIntegralBase<int >: true_t {}; template<> struct __OctaIsIntegral<int >: true_t {};
template<> struct IsIntegralBase<uint >: true_t {}; template<> struct __OctaIsIntegral<uint >: true_t {};
template<> struct IsIntegralBase<long >: true_t {}; template<> struct __OctaIsIntegral<long >: true_t {};
template<> struct IsIntegralBase<ulong >: true_t {}; template<> struct __OctaIsIntegral<ulong >: true_t {};
template<> struct IsIntegralBase<llong >: true_t {}; template<> struct __OctaIsIntegral<llong >: true_t {};
template<> struct IsIntegralBase<ullong>: true_t {}; template<> struct __OctaIsIntegral<ullong>: true_t {};
template<typename T> template<typename T>
struct IsIntegral: IsIntegralBase<typename RemoveConstVolatile<T>::type> {}; struct IsIntegral: __OctaIsIntegral<typename RemoveCV<T>::type> {};
/* is floating point */ /* is floating point */
template<typename T> struct IsFloatingPointBase : false_t {}; template<typename T> struct __OctaIsFloatingPoint: false_t {};
template<> struct IsFloatingPointBase<float >: true_t {}; template<> struct __OctaIsFloatingPoint<float >: true_t {};
template<> struct IsFloatingPointBase<double >: true_t {}; template<> struct __OctaIsFloatingPoint<double >: true_t {};
template<> struct IsFloatingPointBase<ldouble>: true_t {}; template<> struct __OctaIsFloatingPoint<ldouble>: true_t {};
template<typename T> template<typename T>
struct IsFloatingPoint: IsFloatingPointBase<typename RemoveConstVolatile<T>::type> {}; struct IsFloatingPoint: __OctaIsFloatingPoint<typename RemoveCV<T>::type> {};
/* is array */ /* is array */
@ -96,11 +97,11 @@ namespace octa {
/* is pointer */ /* is pointer */
template<typename > struct IsPointerBase : false_t {}; template<typename > struct __OctaIsPointer : false_t {};
template<typename T> struct IsPointerBase<T *>: true_t {}; template<typename T> struct __OctaIsPointer<T *>: true_t {};
template<typename T> template<typename T>
struct IsPointer: IsPointerBase<typename RemoveConstVolatile<T>::type> {}; struct IsPointer: __OctaIsPointer<typename RemoveCV<T>::type> {};
/* is lvalue reference */ /* is lvalue reference */
@ -126,29 +127,25 @@ namespace octa {
/* is function */ /* is function */
template<typename> struct IsReference; struct __OctaFunctionTestDummy {};
namespace internal { template<typename T> char __octa_function_test(T *);
struct FunctionTestDummy {}; template<typename T> char __octa_function_test(__OctaFunctionTestDummy);
template<typename T> int __octa_function_test(...);
template<typename T> char function_test(T *); template<typename T> T &__octa_function_source(int);
template<typename T> char function_test(FunctionTestDummy); template<typename T> __OctaFunctionTestDummy __octa_function_source(...);
template<typename T> int function_test(...);
template<typename T> T &function_source(int);
template<typename T> FunctionTestDummy function_source(...);
}
template<typename T, bool = IsClass<T>::value || IsUnion<T>::value template<typename T, bool = IsClass<T>::value || IsUnion<T>::value
|| IsVoid<T>::value || IsReference<T>::value || IsVoid<T>::value || IsReference<T>::value
|| IsNullPointer<T>::value || IsNullPointer<T>::value
> struct IsFunctionBase: IntegralConstant<bool, > struct __OctaIsFunction: IntegralConstant<bool,
sizeof(internal::function_test<T>(internal::function_source<T>(0))) == 1 sizeof(__octa_function_test<T>(__octa_function_source<T>(0))) == 1
> {}; > {};
template<typename T> struct IsFunctionBase<T, true>: false_t {}; template<typename T> struct __OctaIsFunction<T, true>: false_t {};
template<typename T> struct IsFunction: IsFunctionBase<T> {}; template<typename T> struct IsFunction: __OctaIsFunction<T> {};
/* is arithmetic */ /* is arithmetic */
@ -170,38 +167,42 @@ namespace octa {
/* is pointer to member */ /* is pointer to member */
template<typename> struct IsMemberPointerBase: false_t {}; template<typename>
struct __OctaIsMemberPointer: false_t {};
template<typename T, typename U> template<typename T, typename U>
struct IsMemberPointerBase<T U::*>: true_t {}; struct __OctaIsMemberPointer<T U::*>: true_t {};
template<typename T> template<typename T>
struct IsMemberPointer: IsMemberPointerBase< struct IsMemberPointer: __OctaIsMemberPointer<
typename RemoveConstVolatile<T>::type typename RemoveCV<T>::type
> {}; > {};
/* is pointer to member object */ /* is pointer to member object */
template<typename> struct IsMemberObjectPointerBase: false_t {}; template<typename>
struct __OctaIsMemberObjectPointer: false_t {};
template<typename T, typename U> template<typename T, typename U>
struct IsMemberObjectPointerBase<T U::*>: IntegralConstant<bool, struct __OctaIsMemberObjectPointer<T U::*>: IntegralConstant<bool,
!IsFunction<T>::value !IsFunction<T>::value
> {}; > {};
template<typename T> struct IsMemberObjectPointer: template<typename T> struct IsMemberObjectPointer:
IsMemberObjectPointerBase<typename RemoveConstVolatile<T>::type> {}; __OctaIsMemberObjectPointer<typename RemoveCV<T>::type> {};
/* is pointer to member function */ /* is pointer to member function */
template<typename> struct IsMemberFunctionPointerBase: false_t {}; template<typename>
struct __OctaIsMemberFunctionPointer: false_t {};
template<typename T, typename U> template<typename T, typename U>
struct IsMemberFunctionPointerBase<T U::*>: IntegralConstant<bool, struct __OctaIsMemberFunctionPointer<T U::*>: IntegralConstant<bool,
IsFunction<T>::value IsFunction<T>::value
> {}; > {};
template<typename T> struct IsMemberFunctionPointer: template<typename T> struct IsMemberFunctionPointer:
IsMemberFunctionPointerBase<typename RemoveConstVolatile<T>::type> {}; __OctaIsMemberFunctionPointer<typename RemoveCV<T>::type> {};
/* is reference */ /* is reference */
@ -239,7 +240,8 @@ namespace octa {
/* is empty */ /* is empty */
template<typename T> struct IsEmpty: IntegralConstant<bool, __is_empty(T)> {}; template<typename T>
struct IsEmpty: IntegralConstant<bool, __is_empty(T)> {};
/* is POD */ /* is POD */
@ -252,16 +254,18 @@ namespace octa {
/* is signed */ /* is signed */
template<typename T> struct IsSigned: IntegralConstant<bool, T(-1) < T(0)> {}; template<typename T>
struct IsSigned: IntegralConstant<bool, T(-1) < T(0)> {};
/* is unsigned */ /* is unsigned */
template<typename T> struct IsUnsigned: IntegralConstant<bool, T(0) < T(-1)> {}; template<typename T>
struct IsUnsigned: IntegralConstant<bool, T(0) < T(-1)> {};
/* is standard layout */ /* is standard layout */
template<typename T> struct RemoveAllExtents; template<typename T>
template<typename T> struct IsStandardLayout: IntegralConstant<bool, struct IsStandardLayout: IntegralConstant<bool,
IsScalar<typename RemoveAllExtents<T>::type>::value IsScalar<typename RemoveAllExtents<T>::type>::value
> {}; > {};
@ -282,8 +286,6 @@ namespace octa {
/* is trivial */ /* is trivial */
template<typename> struct IsTriviallyDefaultConstructible;
template<typename T> template<typename T>
struct IsTrivial: IntegralConstant<bool, struct IsTrivial: IntegralConstant<bool,
(IsTriviallyCopyable<T>::value && IsTriviallyDefaultConstructible<T>::value) (IsTriviallyCopyable<T>::value && IsTriviallyDefaultConstructible<T>::value)
@ -292,15 +294,152 @@ namespace octa {
/* has virtual destructor */ /* has virtual destructor */
template<typename T> template<typename T>
struct HasVirtualDestructor: IntegralConstant<bool, __has_virtual_destructor(T)> {}; struct HasVirtualDestructor: IntegralConstant<bool,
__has_virtual_destructor(T)
> {};
/* is destructible - libc++ used as ref */ /* is constructible */
template<typename> struct IsDestructibleApply { typedef int type; }; template<typename, typename T> struct __OctaSelect2nd { typedef T type; };
struct __OctaAny { __OctaAny(...); };
template<typename T, typename ...A> typename __OctaSelect2nd<
decltype(octa::move(T(octa::declval<A>()...))), true_t
>::type __octa_is_ctible_test(T &&, A &&...);
template<typename ...A> false_t __octa_is_ctible_test(__OctaAny, A &&...);
template<bool, typename T, typename ...A>
struct __OctaCtibleCore: CommonType<
decltype(__octa_is_ctible_test(octa::declval<T>(),
octa::declval<A>()...))
>::type {};
/* function types are not constructible */
template<typename R, typename ...A1, typename ...A2>
struct __OctaCtibleCore<false, R(A1...), A2...>: false_t {};
/* scalars are default constructible, refs are not */
template<typename T>
struct __OctaCtibleCore<true, T>: IsScalar<T> {};
/* scalars and references are constructible from one arg if
* implicitly convertible to scalar or reference */
template<typename T>
struct __OctaCtibleRef {
static true_t test(T);
static false_t test(...);
};
template<typename T, typename U>
struct __OctaCtibleCore<true, T, U>: CommonType<
decltype(__OctaCtibleRef<T>::test(octa::declval<U>()))
>::type {};
/* scalars and references are not constructible from multiple args */
template<typename T, typename U, typename ...A>
struct __OctaCtibleCore<true, T, U, A...>: false_t {};
/* treat scalars and refs separately */
template<bool, typename T, typename ...A>
struct __OctaCtibleVoidCheck: __OctaCtibleCore<
(IsScalar<T>::value || IsReference<T>::value), T, A...
> {};
/* if any of T or A is void, IsConstructible should be false */
template<typename T, typename ...A>
struct __OctaCtibleVoidCheck<true, T, A...>: false_t {};
template<typename ...A> struct __OctaCtibleContainsVoid;
template<> struct __OctaCtibleContainsVoid<>: false_t {};
template<typename T, typename ...A>
struct __OctaCtibleContainsVoid<T, A...> {
static constexpr bool value = IsVoid<T>::value
|| __OctaCtibleContainsVoid<A...>::value;
};
/* entry point */
template<typename T, typename ...A>
struct __OctaCtible: __OctaCtibleVoidCheck<
__OctaCtibleContainsVoid<T, A...>::value || IsAbstract<T>::value,
T, A...
> {};
/* array types are default constructible if their element type is */
template<typename T, size_t N>
struct __OctaCtibleCore<false, T[N]>: __OctaCtible<
typename RemoveAllExtents<T>::type
> {};
/* otherwise array types are not constructible by this syntax */
template<typename T, size_t N, typename ...A>
struct __OctaCtibleCore<false, T[N], A...>: false_t {};
/* incomplete array types are not constructible */
template<typename T, typename ...A>
struct __OctaCtibleCore<false, T[], A...>: false_t {};
template<typename T, typename ...A>
struct IsConstructible: __OctaCtible<T, A...> {};
/* is default constructible */
template<typename T> struct IsDefaultConstructible: IsConstructible<T> {};
/* is copy constructible */
template<typename T> struct IsCopyConstructible: IsConstructible<T,
typename AddLvalueReference<typename AddConst<T>::type>::type
> {};
/* is move constructible */
template<typename T> struct IsMoveConstructible: IsConstructible<T,
typename internal::AddRvalueReference<T>::type
> {};
/* is assignable */
template<typename T, typename U> typename __OctaSelect2nd<
decltype((octa::declval<T>() = octa::declval<U>())), true_t
>::type __octa_assign_test(T &&, U &&);
template<typename T> false_t __octa_assign_test(__OctaAny, T &&);
template<typename T, typename U, bool = IsVoid<T>::value || IsVoid<U>::value>
struct __OctaIsAssignable: CommonType<
decltype(__octa_assign_test(octa::declval<T>(), octa::declval<U>()))
>::type {};
template<typename T, typename U>
struct __OctaIsAssignable<T, U, true>: false_t {};
template<typename T, typename U>
struct IsAssignable: __OctaIsAssignable<T, U> {};
/* is copy assignable */
template<typename T> struct IsCopyAssignable: IsAssignable<
typename AddLvalueReference<T>::type,
typename AddLvalueReference<typename AddConst<T>::type>::type
> {};
/* is move assignable */
template<typename T> struct IsMoveAssignable: IsAssignable<
typename AddLvalueReference<T>::type,
const typename internal::AddRvalueReference<T>::type
> {};
/* is destructible */
template<typename> struct __OctaIsDtibleApply { typedef int type; };
template<typename T> struct IsDestructorWellformed { template<typename T> struct IsDestructorWellformed {
template<typename TT> static char test(typename IsDestructibleApply< template<typename TT> static char test(typename __OctaIsDtibleApply<
decltype(declval<TT &>().~TT()) decltype(octa::declval<TT &>().~TT())
>::type); >::type);
template<typename TT> static int test(...); template<typename TT> static int test(...);
@ -308,25 +447,25 @@ namespace octa {
static constexpr bool value = (sizeof(test<T>(12)) == sizeof(char)); static constexpr bool value = (sizeof(test<T>(12)) == sizeof(char));
}; };
template<typename, bool> struct DestructibleImpl; template<typename, bool> struct __OctaDtibleImpl;
template<typename T> template<typename T>
struct DestructibleImpl<T, false>: IntegralConstant<bool, struct __OctaDtibleImpl<T, false>: IntegralConstant<bool,
IsDestructorWellformed<typename RemoveAllExtents<T>::type>::value IsDestructorWellformed<typename RemoveAllExtents<T>::type>::value
> {}; > {};
template<typename T> template<typename T>
struct DestructibleImpl<T, true>: true_t {}; struct __OctaDtibleImpl<T, true>: true_t {};
template<typename T, bool> struct DestructibleFalse; template<typename T, bool> struct __OctaDtibleFalse;
template<typename T> struct DestructibleFalse<T, false> template<typename T> struct __OctaDtibleFalse<T, false>
: DestructibleImpl<T, IsReference<T>::value> {}; : __OctaDtibleImpl<T, IsReference<T>::value> {};
template<typename T> struct DestructibleFalse<T, true>: false_t {}; template<typename T> struct __OctaDtibleFalse<T, true>: false_t {};
template<typename T> template<typename T>
struct IsDestructible: DestructibleFalse<T, IsFunction<T>::value> {}; struct IsDestructible: __OctaDtibleFalse<T, IsFunction<T>::value> {};
template<typename T> struct IsDestructible<T[] >: false_t {}; template<typename T> struct IsDestructible<T[] >: false_t {};
template< > struct IsDestructible<void>: false_t {}; template< > struct IsDestructible<void>: false_t {};
@ -363,8 +502,6 @@ namespace octa {
/* is trivially copy constructible */ /* is trivially copy constructible */
template<typename> struct AddLvalueReference;
template<typename T> template<typename T>
struct IsTriviallyCopyConstructible: IsTriviallyConstructible<T, struct IsTriviallyCopyConstructible: IsTriviallyConstructible<T,
typename AddLvalueReference<const T>::type typename AddLvalueReference<const T>::type
@ -404,8 +541,6 @@ namespace octa {
/* is trivially copy assignable */ /* is trivially copy assignable */
template<typename> struct AddLvalueReference;
template<typename T> template<typename T>
struct IsTriviallyCopyAssignable: IsTriviallyAssignable<T, struct IsTriviallyCopyAssignable: IsTriviallyAssignable<T,
typename AddLvalueReference<const T>::type typename AddLvalueReference<const T>::type
@ -457,8 +592,6 @@ namespace octa {
/* is nothrow copy constructible */ /* is nothrow copy constructible */
template<typename> struct AddLvalueReference;
template<typename T> template<typename T>
struct IsNothrowCopyConstructible: IsNothrowConstructible<T, struct IsNothrowCopyConstructible: IsNothrowConstructible<T,
typename AddLvalueReference<const T>::type typename AddLvalueReference<const T>::type
@ -498,8 +631,6 @@ namespace octa {
/* is nothrow copy assignable */ /* is nothrow copy assignable */
template<typename> struct AddLvalueReference;
template<typename T> template<typename T>
struct IsNothrowCopyAssignable: IsNothrowAssignable<T, struct IsNothrowCopyAssignable: IsNothrowAssignable<T,
typename AddLvalueReference<const T>::type typename AddLvalueReference<const T>::type
@ -514,15 +645,15 @@ namespace octa {
/* is nothrow destructible */ /* is nothrow destructible */
template<typename, bool> struct IsNothrowDestructibleBase; template<typename, bool> struct __OctaIsNothrowDtible;
template<typename T> template<typename T>
struct IsNothrowDestructibleBase<T, false>: IntegralConstant<bool, struct __OctaIsNothrowDtible<T, false>: IntegralConstant<bool,
noexcept(declval<T>().~T()) noexcept(octa::declval<T>().~T())
> {}; > {};
template<typename T> template<typename T>
struct IsNothrowDestructible: IsNothrowDestructibleBase<T, struct IsNothrowDestructible: __OctaIsNothrowDtible<T,
IsDestructible<T>::value IsDestructible<T>::value
> {}; > {};
@ -544,15 +675,15 @@ namespace octa {
template<typename F, typename T, bool = IsVoid<F>::value template<typename F, typename T, bool = IsVoid<F>::value
|| IsFunction<T>::value || IsArray<T>::value || IsFunction<T>::value || IsArray<T>::value
> struct IsConvertibleBase { > struct __OctaIsConvertible {
typedef typename IsVoid<T>::type type; typedef typename IsVoid<T>::type type;
}; };
template<typename F, typename T> struct IsConvertibleBase<F, T, false> { template<typename F, typename T> struct __OctaIsConvertible<F, T, false> {
template<typename TT> static void test_f(TT); template<typename TT> static void test_f(TT);
template<typename FF, typename TT, template<typename FF, typename TT,
typename = decltype(test_f<TT>(declval<FF>())) typename = decltype(test_f<TT>(octa::declval<FF>()))
> static true_t test(int); > static true_t test(int);
template<typename, typename> static false_t test(...); template<typename, typename> static false_t test(...);
@ -561,7 +692,7 @@ namespace octa {
}; };
template<typename F, typename T> template<typename F, typename T>
struct IsConvertible: IsConvertibleBase<F, T>::type {}; struct IsConvertible: __OctaIsConvertible<F, T>::type {};
/* type equality */ /* type equality */
@ -604,7 +735,7 @@ namespace octa {
template<typename T> struct RemoveVolatile<volatile T> { typedef T type; }; template<typename T> struct RemoveVolatile<volatile T> { typedef T type; };
template<typename T> template<typename T>
struct RemoveConstVolatile { struct RemoveCV {
typedef typename RemoveVolatile<typename RemoveConst<T>::type>::type type; typedef typename RemoveVolatile<typename RemoveConst<T>::type>::type type;
}; };
@ -612,30 +743,30 @@ namespace octa {
template<typename T, bool = IsReference<T>::value template<typename T, bool = IsReference<T>::value
|| IsFunction<T>::value || IsConst<T>::value> || IsFunction<T>::value || IsConst<T>::value>
struct AddConstBase { typedef T type; }; struct __OctaAddConst { typedef T type; };
template<typename T> struct AddConstBase<T, false> { template<typename T> struct __OctaAddConst<T, false> {
typedef const T type; typedef const T type;
}; };
template<typename T> struct AddConst { template<typename T> struct AddConst {
typedef typename AddConstBase<T>::type type; typedef typename __OctaAddConst<T>::type type;
}; };
template<typename T, bool = IsReference<T>::value template<typename T, bool = IsReference<T>::value
|| IsFunction<T>::value || IsVolatile<T>::value> || IsFunction<T>::value || IsVolatile<T>::value>
struct AddVolatileBase { typedef T type; }; struct __OctaAddVolatile { typedef T type; };
template<typename T> struct AddVolatileBase<T, false> { template<typename T> struct __OctaAddVolatile<T, false> {
typedef volatile T type; typedef volatile T type;
}; };
template<typename T> struct AddVolatile { template<typename T> struct AddVolatile {
typedef typename AddVolatileBase<T>::type type; typedef typename __OctaAddVolatile<T>::type type;
}; };
template<typename T> template<typename T>
struct AddConstVolatile { struct AddCV {
typedef typename AddConst<typename AddVolatile<T>::type>::type type; typedef typename AddConst<typename AddVolatile<T>::type>::type type;
}; };
@ -703,141 +834,137 @@ namespace octa {
* shamelessly copied from graphitemaster @ neothyne * shamelessly copied from graphitemaster @ neothyne
*/ */
namespace internal { template<typename T, typename U> struct __OctaTL {
template<typename T, typename U> struct TypeList { typedef T first;
typedef T first; typedef U rest;
typedef U rest; };
};
/* not a type */ /* not a type */
struct NAT { struct __OctaNAT {
NAT() = delete; __OctaNAT() = delete;
NAT(const NAT &) = delete; __OctaNAT(const __OctaNAT &) = delete;
NAT &operator=(const NAT &) = delete; __OctaNAT &operator=(const __OctaNAT &) = delete;
~NAT() = delete; ~__OctaNAT() = delete;
}; };
typedef TypeList<schar, typedef __OctaTL<schar,
TypeList<short, __OctaTL<short,
TypeList<int, __OctaTL<int,
TypeList<long, __OctaTL<long,
TypeList<llong, NAT>>>>> stypes; __OctaTL<llong, __OctaNAT>>>>> stypes;
typedef TypeList<uchar, typedef __OctaTL<uchar,
TypeList<ushort, __OctaTL<ushort,
TypeList<uint, __OctaTL<uint,
TypeList<ulong, __OctaTL<ulong,
TypeList<ullong, NAT>>>>> utypes; __OctaTL<ullong, __OctaNAT>>>>> utypes;
template<typename T, size_t N, bool = (N <= sizeof(typename T::first))> template<typename T, size_t N, bool = (N <= sizeof(typename T::first))>
struct TypeFindFirst; struct __OctaTypeFindFirst;
template<typename T, typename U, size_t N> template<typename T, typename U, size_t N>
struct TypeFindFirst<TypeList<T, U>, N, true> { struct __OctaTypeFindFirst<__OctaTL<T, U>, N, true> {
typedef T type; typedef T type;
}; };
template<typename T, typename U, size_t N> template<typename T, typename U, size_t N>
struct TypeFindFirst<TypeList<T, U>, N, false> { struct __OctaTypeFindFirst<__OctaTL<T, U>, N, false> {
typedef typename TypeFindFirst<U, N>::type type; typedef typename __OctaTypeFindFirst<U, N>::type type;
}; };
template<typename T, typename U, template<typename T, typename U,
bool = IsConst<typename RemoveReference<T>::type>::value, bool = IsConst<typename RemoveReference<T>::type>::value,
bool = IsVolatile<typename RemoveReference<T>::type>::value bool = IsVolatile<typename RemoveReference<T>::type>::value
> struct ApplyConstVolatile { > struct __OctaApplyCV {
typedef U type; typedef U type;
}; };
template<typename T, typename U> template<typename T, typename U>
struct ApplyConstVolatile<T, U, true, false> { /* const */ struct __OctaApplyCV<T, U, true, false> { /* const */
typedef const U type; typedef const U type;
}; };
template<typename T, typename U> template<typename T, typename U>
struct ApplyConstVolatile<T, U, false, true> { /* volatile */ struct __OctaApplyCV<T, U, false, true> { /* volatile */
typedef volatile U type; typedef volatile U type;
}; };
template<typename T, typename U> template<typename T, typename U>
struct ApplyConstVolatile<T, U, true, true> { /* const volatile */ struct __OctaApplyCV<T, U, true, true> { /* const volatile */
typedef const volatile U type; typedef const volatile U type;
}; };
template<typename T, typename U> template<typename T, typename U>
struct ApplyConstVolatile<T &, U, true, false> { /* const */ struct __OctaApplyCV<T &, U, true, false> { /* const */
typedef const U &type; typedef const U &type;
}; };
template<typename T, typename U> template<typename T, typename U>
struct ApplyConstVolatile<T &, U, false, true> { /* volatile */ struct __OctaApplyCV<T &, U, false, true> { /* volatile */
typedef volatile U &type; typedef volatile U &type;
}; };
template<typename T, typename U> template<typename T, typename U>
struct ApplyConstVolatile<T &, U, true, true> { /* const volatile */ struct __OctaApplyCV<T &, U, true, true> { /* const volatile */
typedef const volatile U &type; typedef const volatile U &type;
}; };
template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value> template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value>
struct MakeSigned {}; struct __OctaMakeSigned {};
template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value> template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value>
struct MakeUnsigned {}; struct __OctaMakeUnsigned {};
template<typename T> template<typename T>
struct MakeSigned<T, true> { struct __OctaMakeSigned<T, true> {
typedef typename TypeFindFirst<stypes, sizeof(T)>::type type; typedef typename __OctaTypeFindFirst<stypes, sizeof(T)>::type type;
}; };
template<typename T> template<typename T>
struct MakeUnsigned<T, true> { struct __OctaMakeUnsigned<T, true> {
typedef typename TypeFindFirst<utypes, sizeof(T)>::type type; typedef typename __OctaTypeFindFirst<utypes, sizeof(T)>::type type;
}; };
template<> struct MakeSigned<bool , true> {}; template<> struct __OctaMakeSigned<bool , true> {};
template<> struct MakeSigned<schar , true> { typedef schar type; }; template<> struct __OctaMakeSigned<schar , true> { typedef schar type; };
template<> struct MakeSigned<uchar , true> { typedef schar type; }; template<> struct __OctaMakeSigned<uchar , true> { typedef schar type; };
template<> struct MakeSigned<short , true> { typedef short type; }; template<> struct __OctaMakeSigned<short , true> { typedef short type; };
template<> struct MakeSigned<ushort, true> { typedef short type; }; template<> struct __OctaMakeSigned<ushort, true> { typedef short type; };
template<> struct MakeSigned<int , true> { typedef int type; }; template<> struct __OctaMakeSigned<int , true> { typedef int type; };
template<> struct MakeSigned<uint , true> { typedef int type; }; template<> struct __OctaMakeSigned<uint , true> { typedef int type; };
template<> struct MakeSigned<long , true> { typedef long type; }; template<> struct __OctaMakeSigned<long , true> { typedef long type; };
template<> struct MakeSigned<ulong , true> { typedef long type; }; template<> struct __OctaMakeSigned<ulong , true> { typedef long type; };
template<> struct MakeSigned<llong , true> { typedef llong type; }; template<> struct __OctaMakeSigned<llong , true> { typedef llong type; };
template<> struct MakeSigned<ullong, true> { typedef llong type; }; template<> struct __OctaMakeSigned<ullong, true> { typedef llong type; };
template<> struct MakeUnsigned<bool , true> {}; template<> struct __OctaMakeUnsigned<bool , true> {};
template<> struct MakeUnsigned<schar , true> { typedef uchar type; }; template<> struct __OctaMakeUnsigned<schar , true> { typedef uchar type; };
template<> struct MakeUnsigned<uchar , true> { typedef uchar type; }; template<> struct __OctaMakeUnsigned<uchar , true> { typedef uchar type; };
template<> struct MakeUnsigned<short , true> { typedef ushort type; }; template<> struct __OctaMakeUnsigned<short , true> { typedef ushort type; };
template<> struct MakeUnsigned<ushort, true> { typedef ushort type; }; template<> struct __OctaMakeUnsigned<ushort, true> { typedef ushort type; };
template<> struct MakeUnsigned<int , true> { typedef uint type; }; template<> struct __OctaMakeUnsigned<int , true> { typedef uint type; };
template<> struct MakeUnsigned<uint , true> { typedef uint type; }; template<> struct __OctaMakeUnsigned<uint , true> { typedef uint type; };
template<> struct MakeUnsigned<long , true> { typedef ulong type; }; template<> struct __OctaMakeUnsigned<long , true> { typedef ulong type; };
template<> struct MakeUnsigned<ulong , true> { typedef ulong type; }; template<> struct __OctaMakeUnsigned<ulong , true> { typedef ulong type; };
template<> struct MakeUnsigned<llong , true> { typedef ullong type; }; template<> struct __OctaMakeUnsigned<llong , true> { typedef ullong type; };
template<> struct MakeUnsigned<ullong, true> { typedef ullong type; }; template<> struct __OctaMakeUnsigned<ullong, true> { typedef ullong type; };
}
template<typename T> struct MakeSigned { template<typename T> struct MakeSigned {
typedef typename internal::ApplyConstVolatile<T, typedef typename __OctaApplyCV<T,
typename internal::MakeSigned< typename __OctaMakeSigned<
typename RemoveConstVolatile<T>::type typename RemoveCV<T>::type
>::type >::type
>::type type; >::type type;
}; };
template<typename T> struct MakeUnsigned { template<typename T> struct MakeUnsigned {
typedef typename internal::ApplyConstVolatile<T, typedef typename __OctaApplyCV<T,
typename internal::MakeUnsigned< typename __OctaMakeUnsigned<
typename RemoveConstVolatile<T>::type typename RemoveCV<T>::type
>::type >::type
>::type type; >::type type;
}; };
/* common type */
/* conditional */ /* conditional */
template<bool cond, typename T, typename U> template<bool cond, typename T, typename U>
@ -852,49 +979,48 @@ namespace octa {
/* result of call at compile time */ /* result of call at compile time */
namespace internal { template<typename F, typename ...A>
template<typename F, typename ...A> inline auto __octa_rof_invoke(F &&f, A &&...args) ->
inline auto result_of_invoke(F &&f, A &&...args) -> decltype(forward<F>(f)(forward<A>(args)...)) {
decltype(forward<F>(f)(forward<A>(args)...)) { return forward<F>(f)(forward<A>(args)...);
return forward<F>(f)(forward<A>(args)...); }
} template<typename B, typename T, typename D>
template<typename B, typename T, typename D> inline auto __octa_rof_invoke(T B::*pmd, D &&ref) ->
inline auto result_of_invoke(T B::*pmd, D &&ref) -> decltype(forward<D>(ref).*pmd) {
decltype(forward<D>(ref).*pmd) { return forward<D>(ref).*pmd;
return forward<D>(ref).*pmd; }
} template<typename PMD, typename P>
template<typename PMD, typename P> inline auto __octa_rof_invoke(PMD &&pmd, P &&ptr) ->
inline auto result_of_invoke(PMD &&pmd, P &&ptr) -> decltype((*forward<P>(ptr)).*forward<PMD>(pmd)) {
decltype((*forward<P>(ptr)).*forward<PMD>(pmd)) { return (*forward<P>(ptr)).*forward<PMD>(pmd);
return (*forward<P>(ptr)).*forward<PMD>(pmd); }
} template<typename B, typename T, typename D, typename ...A>
template<typename B, typename T, typename D, typename ...A> inline auto __octa_rof_invoke(T B::*pmf, D &&ref, A &&...args) ->
inline auto result_of_invoke(T B::*pmf, D &&ref, A &&...args) -> decltype((forward<D>(ref).*pmf)(forward<A>(args)...)) {
decltype((forward<D>(ref).*pmf)(forward<A>(args)...)) { return (forward<D>(ref).*pmf)(forward<A>(args)...);
return (forward<D>(ref).*pmf)(forward<A>(args)...); }
} template<typename PMF, typename P, typename ...A>
template<typename PMF, typename P, typename ...A> inline auto __octa_rof_invoke(PMF &&pmf, P &&ptr, A &&...args) ->
inline auto result_of_invoke(PMF &&pmf, P &&ptr, A &&...args) -> decltype(((*forward<P>(ptr)).*forward<PMF>(pmf))(forward<A>(args)...)) {
decltype(((*forward<P>(ptr)).*forward<PMF>(pmf))(forward<A>(args)...)) { return ((*forward<P>(ptr)).*forward<PMF>(pmf))(forward<A>(args)...);
return ((*forward<P>(ptr)).*forward<PMF>(pmf))(forward<A>(args)...);
}
template<typename, typename = void>
struct ResultOf {};
template<typename F, typename ...A>
struct ResultOf<F(A...), decltype(void(result_of_invoke(declval<F>(),
declval<A>()...)))> {
using type = decltype(result_of_invoke(declval<F>(), declval<A>()...));
};
} }
template<typename T> struct ResultOf: internal::ResultOf<T> {}; template<typename, typename = void>
struct __OctaResultOf {};
template<typename F, typename ...A>
struct __OctaResultOf<F(A...), decltype(void(__octa_rof_invoke(
octa::declval<F>(), octa::declval<A>()...)))> {
using type = decltype(__octa_rof_invoke(octa::declval<F>(),
octa::declval<A>()...));
};
/* enable_if */ template<typename T> struct ResultOf: __OctaResultOf<T> {};
template<bool B, typename T = void> struct enable_if {}; /* enable if */
template<typename T> struct enable_if<true, T> { typedef T type; }; template<bool B, typename T = void> struct EnableIf {};
template<typename T> struct EnableIf<true, T> { typedef T type; };
/* decay */ /* decay */
@ -907,7 +1033,7 @@ namespace octa {
typename RemoveExtent<U>::type *, typename RemoveExtent<U>::type *,
typename Conditional<IsFunction<U>::value, typename Conditional<IsFunction<U>::value,
typename AddPointer<U>::type, typename AddPointer<U>::type,
typename RemoveConstVolatile<U>::type typename RemoveCV<U>::type
>::type >::type
>::type type; >::type type;
}; };
@ -921,7 +1047,7 @@ namespace octa {
}; };
template<typename T, typename U> struct CommonType<T, U> { template<typename T, typename U> struct CommonType<T, U> {
typedef Decay<decltype(true ? declval<T>() : declval<U>())> type; typedef Decay<decltype(true ? octa::declval<T>() : octa::declval<U>())> type;
}; };
template<typename T, typename U, typename ...V> template<typename T, typename U, typename ...V>
@ -931,17 +1057,15 @@ namespace octa {
/* aligned storage */ /* aligned storage */
namespace internal { template<size_t N> struct __OctaAlignedTest {
template<size_t N> struct AlignedStorageTest { union type {
union type { uchar data[N];
uchar data[N]; octa::max_align_t align;
octa::max_align_t align;
};
}; };
}; };
template<size_t N, size_t A template<size_t N, size_t A
= alignof(typename internal::AlignedStorageTest<N>::type) = alignof(typename __OctaAlignedTest<N>::type)
> struct AlignedStorage { > struct AlignedStorage {
struct type { struct type {
alignas(A) uchar data[N]; alignas(A) uchar data[N];
@ -950,39 +1074,37 @@ namespace octa {
/* aligned union */ /* aligned union */
namespace internal { template<size_t ...N> struct __OctaAlignMax;
template<size_t ...N> struct AlignMax;
template<size_t N> struct AlignMax<N> { template<size_t N> struct __OctaAlignMax<N> {
static constexpr size_t value = N; static constexpr size_t value = N;
}; };
template<size_t N1, size_t N2> struct AlignMax<N1, N2> { template<size_t N1, size_t N2> struct __OctaAlignMax<N1, N2> {
static constexpr size_t value = (N1 > N2) ? N1 : N2; static constexpr size_t value = (N1 > N2) ? N1 : N2;
}; };
template<size_t N1, size_t N2, size_t ...N> template<size_t N1, size_t N2, size_t ...N>
struct AlignMax<N1, N2, N...> { struct __OctaAlignMax<N1, N2, N...> {
static constexpr size_t value static constexpr size_t value
= AlignMax<AlignMax<N1, N2>::value, N...>::value; = __OctaAlignMax<__OctaAlignMax<N1, N2>::value, N...>::value;
}; };
}
template<size_t N, typename ...T> struct AlignedUnion { template<size_t N, typename ...T> struct AlignedUnion {
static constexpr size_t alignment_value static constexpr size_t alignment_value
= internal::AlignMax<alignof(T)...>::value; = __OctaAlignMax<alignof(T)...>::value;
struct type { struct type {
alignas(alignment_value) uchar data[internal::AlignMax<N, alignas(alignment_value) uchar data[__OctaAlignMax<N,
sizeof(T)...>::value]; sizeof(T)...>::value];
}; };
}; };
/* underlying type */ /* underlying type */
template<typename T, bool = IsEnum<T>::value> struct UnderlyingTypeBase; template<typename T, bool = IsEnum<T>::value> struct __OctaUnderlyingType;
template<typename T> struct UnderlyingTypeBase<T, true> { template<typename T> struct __OctaUnderlyingType<T, true> {
typedef typename Conditional<IsSigned<T>::value, typedef typename Conditional<IsSigned<T>::value,
typename MakeSigned<T>::type, typename MakeSigned<T>::type,
typename MakeUnsigned<T>::type typename MakeUnsigned<T>::type
@ -990,7 +1112,7 @@ namespace octa {
}; };
template<typename T> struct UnderlyingType { template<typename T> struct UnderlyingType {
typedef typename UnderlyingTypeBase<T>::type type; typedef typename __OctaUnderlyingType<T>::type type;
}; };
} }