2015-04-13 21:25:31 +00:00
|
|
|
/* Type traits for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OCTA_TRAITS_H
|
|
|
|
#define OCTA_TRAITS_H
|
|
|
|
|
2015-04-13 22:04:25 +00:00
|
|
|
#include <stddef.h>
|
|
|
|
|
2015-04-13 21:25:31 +00:00
|
|
|
#include "octa/types.h"
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
namespace octa {
|
|
|
|
/* forward declarations */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename> struct __OctaRemoveCV;
|
|
|
|
template<typename> struct __OctaAddLR;
|
|
|
|
template<typename> struct __OctaAddRR;
|
|
|
|
template<typename> struct __OctaAddConst;
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename> struct IsReference;
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename> struct __OctaRemoveReference;
|
|
|
|
template<typename> struct __OctaRemoveAllExtents;
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename> struct IsTriviallyDefaultConstructible;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename...> struct __OctaCommonType;
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-04-23 19:53:05 +00:00
|
|
|
/* declval also defined here to avoid including utility.h */
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> typename __OctaAddRR<T>::type __octa_declval();
|
2015-04-23 19:53:05 +00:00
|
|
|
|
2015-04-13 21:56:02 +00:00
|
|
|
/* integral constant */
|
|
|
|
|
2015-04-13 21:25:31 +00:00
|
|
|
template<typename T, T val>
|
|
|
|
struct IntegralConstant {
|
2015-04-23 17:47:33 +00:00
|
|
|
static constexpr T value = val;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
|
|
|
typedef T value_type;
|
2015-04-13 22:19:52 +00:00
|
|
|
typedef IntegralConstant<T, val> type;
|
2015-04-18 17:32:25 +00:00
|
|
|
|
|
|
|
constexpr operator value_type() const { return value; }
|
|
|
|
constexpr value_type operator()() const { return value; }
|
2015-04-13 21:25:31 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
typedef IntegralConstant<bool, true> True;
|
|
|
|
typedef IntegralConstant<bool, false> False;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
template<typename T, T val> constexpr T IntegralConstant<T, val>::value;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
/* is void */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaIsVoid : False {};
|
|
|
|
template< > struct __OctaIsVoid<void>: True {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsVoid: __OctaIsVoid<typename __OctaRemoveCV<T>::type> {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
|
|
|
/* is null pointer */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename> struct __OctaIsNullPointer : False {};
|
|
|
|
template< > struct __OctaIsNullPointer<nullptr_t>: True {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T> struct IsNullPointer: __OctaIsNullPointer<
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaRemoveCV<T>::type
|
2015-04-22 23:26:29 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-13 21:56:02 +00:00
|
|
|
/* is integer */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaIsIntegral: False {};
|
|
|
|
|
|
|
|
template<> struct __OctaIsIntegral<bool >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<char >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<uchar >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<schar >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<short >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<ushort>: True {};
|
|
|
|
template<> struct __OctaIsIntegral<int >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<uint >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<long >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<ulong >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<llong >: True {};
|
|
|
|
template<> struct __OctaIsIntegral<ullong>: True {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsIntegral: __OctaIsIntegral<typename __OctaRemoveCV<T>::type> {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
|
|
|
/* is floating point */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaIsFloatingPoint: False {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaIsFloatingPoint<float >: True {};
|
|
|
|
template<> struct __OctaIsFloatingPoint<double >: True {};
|
|
|
|
template<> struct __OctaIsFloatingPoint<ldouble>: True {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsFloatingPoint: __OctaIsFloatingPoint<typename __OctaRemoveCV<T>::type> {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
/* is array */
|
2015-04-13 22:19:52 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename > struct IsArray : False {};
|
|
|
|
template<typename T > struct IsArray<T[] >: True {};
|
|
|
|
template<typename T, size_t N> struct IsArray<T[N]>: True {};
|
2015-04-13 22:19:52 +00:00
|
|
|
|
2015-04-13 21:56:02 +00:00
|
|
|
/* is pointer */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename > struct __OctaIsPointer : False {};
|
|
|
|
template<typename T> struct __OctaIsPointer<T *>: True {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsPointer: __OctaIsPointer<typename __OctaRemoveCV<T>::type> {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
/* is lvalue reference */
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename > struct IsLvalueReference : False {};
|
|
|
|
template<typename T> struct IsLvalueReference<T &>: True {};
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
/* is rvalue reference */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename > struct IsRvalueReference : False {};
|
|
|
|
template<typename T> struct IsRvalueReference<T &&>: True {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
|
|
|
/* is enum */
|
|
|
|
|
|
|
|
template<typename T> struct IsEnum: IntegralConstant<bool, __is_enum(T)> {};
|
|
|
|
|
|
|
|
/* is union */
|
|
|
|
|
|
|
|
template<typename T> struct IsUnion: IntegralConstant<bool, __is_union(T)> {};
|
|
|
|
|
|
|
|
/* is class */
|
|
|
|
|
|
|
|
template<typename T> struct IsClass: IntegralConstant<bool, __is_class(T)> {};
|
|
|
|
|
2015-04-23 00:46:29 +00:00
|
|
|
/* is function */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
struct __OctaFunctionTestDummy {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T> char __octa_function_test(T *);
|
|
|
|
template<typename T> char __octa_function_test(__OctaFunctionTestDummy);
|
|
|
|
template<typename T> int __octa_function_test(...);
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T> T &__octa_function_source(int);
|
|
|
|
template<typename T> __OctaFunctionTestDummy __octa_function_source(...);
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-04-23 00:46:29 +00:00
|
|
|
template<typename T, bool = IsClass<T>::value || IsUnion<T>::value
|
|
|
|
|| IsVoid<T>::value || IsReference<T>::value
|
|
|
|
|| IsNullPointer<T>::value
|
2015-04-23 19:38:18 +00:00
|
|
|
> struct __OctaIsFunction: IntegralConstant<bool,
|
|
|
|
sizeof(__octa_function_test<T>(__octa_function_source<T>(0))) == 1
|
2015-04-23 00:46:29 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaIsFunction<T, true>: False {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T> struct IsFunction: __OctaIsFunction<T> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
|
|
|
/* is arithmetic */
|
|
|
|
|
|
|
|
template<typename T> struct IsArithmetic: IntegralConstant<bool,
|
2015-04-22 23:26:29 +00:00
|
|
|
(IsIntegral<T>::value || IsFloatingPoint<T>::value)
|
2015-04-14 00:12:00 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
/* is fundamental */
|
|
|
|
|
|
|
|
template<typename T> struct IsFundamental: IntegralConstant<bool,
|
|
|
|
(IsArithmetic<T>::value || IsVoid<T>::value || IsNullPointer<T>::value)
|
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is compound */
|
|
|
|
|
|
|
|
template<typename T> struct IsCompound: IntegralConstant<bool,
|
|
|
|
!IsFundamental<T>::value
|
|
|
|
> {};
|
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
/* is pointer to member */
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaIsMemberPointer: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
template<typename T, typename U>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaIsMemberPointer<T U::*>: True {};
|
2015-04-14 00:12:00 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct IsMemberPointer: __OctaIsMemberPointer<
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaRemoveCV<T>::type
|
2015-04-14 00:12:00 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-23 01:16:48 +00:00
|
|
|
/* is pointer to member object */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaIsMemberObjectPointer: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
template<typename T, typename U>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct __OctaIsMemberObjectPointer<T U::*>: IntegralConstant<bool,
|
2015-04-23 17:47:33 +00:00
|
|
|
!IsFunction<T>::value
|
2015-04-23 01:16:48 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
template<typename T> struct IsMemberObjectPointer:
|
2015-04-24 18:43:20 +00:00
|
|
|
__OctaIsMemberObjectPointer<typename __OctaRemoveCV<T>::type> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
/* is pointer to member function */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaIsMemberFunctionPointer: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
template<typename T, typename U>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct __OctaIsMemberFunctionPointer<T U::*>: IntegralConstant<bool,
|
2015-04-23 17:47:33 +00:00
|
|
|
IsFunction<T>::value
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename T> struct IsMemberFunctionPointer:
|
2015-04-24 18:43:20 +00:00
|
|
|
__OctaIsMemberFunctionPointer<typename __OctaRemoveCV<T>::type> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
/* is reference */
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
template<typename T> struct IsReference: IntegralConstant<bool,
|
|
|
|
(IsLvalueReference<T>::value || IsRvalueReference<T>::value)
|
2015-04-13 22:19:52 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
/* is object */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
template<typename T> struct IsObject: IntegralConstant<bool,
|
|
|
|
(!IsFunction<T>::value && !IsVoid<T>::value && !IsReference<T>::value)
|
|
|
|
> {};
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
/* is scalar */
|
2015-04-13 22:04:25 +00:00
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
template<typename T> struct IsScalar: IntegralConstant<bool,
|
|
|
|
(IsMemberPointer<T>::value || IsPointer<T>::value || IsEnum<T>::value
|
|
|
|
|| IsNullPointer <T>::value || IsArithmetic<T>::value)
|
2015-04-13 22:04:25 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
/* is abstract */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsAbstract: IntegralConstant<bool, __is_abstract(T)> {};
|
|
|
|
|
|
|
|
/* is const */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename > struct IsConst : False {};
|
|
|
|
template<typename T> struct IsConst<const T>: True {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
|
|
|
/* is volatile */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename > struct IsVolatile : False {};
|
|
|
|
template<typename T> struct IsVolatile<volatile T>: True {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
|
|
|
/* is empty */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsEmpty: IntegralConstant<bool, __is_empty(T)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
|
|
|
/* is POD */
|
|
|
|
|
|
|
|
template<typename T> struct IsPOD: IntegralConstant<bool, __is_pod(T)> {};
|
|
|
|
|
|
|
|
/* is polymorphic */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsPolymorphic: IntegralConstant<bool, __is_polymorphic(T)> {};
|
|
|
|
|
|
|
|
/* is signed */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsSigned: IntegralConstant<bool, T(-1) < T(0)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
|
|
|
/* is unsigned */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsUnsigned: IntegralConstant<bool, T(0) < T(-1)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
|
|
|
/* is standard layout */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsStandardLayout: IntegralConstant<bool,
|
2015-04-24 18:43:20 +00:00
|
|
|
IsScalar<typename __OctaRemoveAllExtents<T>::type>::value
|
2015-04-23 00:26:03 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-23 01:16:48 +00:00
|
|
|
/* is literal type */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsLiteralType: IntegralConstant<bool,
|
2015-04-24 18:43:20 +00:00
|
|
|
IsReference<typename __OctaRemoveAllExtents<T>::type>::value
|
2015-04-23 01:16:48 +00:00
|
|
|
|| IsStandardLayout<T>::value
|
|
|
|
> {};
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* is trivially copyable */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyCopyable: IntegralConstant<bool,
|
2015-04-24 18:43:20 +00:00
|
|
|
IsScalar<typename __OctaRemoveAllExtents<T>::type>::value
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is trivial */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsTrivial: IntegralConstant<bool,
|
|
|
|
(IsTriviallyCopyable<T>::value && IsTriviallyDefaultConstructible<T>::value)
|
|
|
|
> {};
|
|
|
|
|
|
|
|
/* has virtual destructor */
|
|
|
|
|
|
|
|
template<typename T>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct HasVirtualDestructor: IntegralConstant<bool,
|
|
|
|
__has_virtual_destructor(T)
|
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is constructible */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
#define __OCTA_MOVE(v) static_cast<typename __OctaRemoveReference<decltype(v)>::type &&>(v)
|
2015-04-23 19:53:05 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename, typename T> struct __OctaSelect2nd { typedef T type; };
|
|
|
|
struct __OctaAny { __OctaAny(...); };
|
|
|
|
|
|
|
|
template<typename T, typename ...A> typename __OctaSelect2nd<
|
2015-04-24 18:43:20 +00:00
|
|
|
decltype(__OCTA_MOVE(T(__octa_declval<A>()...))), True
|
2015-04-23 19:38:18 +00:00
|
|
|
>::type __octa_is_ctible_test(T &&, A &&...);
|
|
|
|
|
2015-04-23 19:53:05 +00:00
|
|
|
#undef __OCTA_MOVE
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename ...A> False __octa_is_ctible_test(__OctaAny, A &&...);
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
template<bool, typename T, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCtibleCore: __OctaCommonType<
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype(__octa_is_ctible_test(__octa_declval<T>(),
|
|
|
|
__octa_declval<A>()...))
|
2015-04-23 19:38:18 +00:00
|
|
|
>::type {};
|
|
|
|
|
|
|
|
/* function types are not constructible */
|
|
|
|
template<typename R, typename ...A1, typename ...A2>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCtibleCore<false, R(A1...), A2...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* 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 {
|
2015-04-24 18:43:20 +00:00
|
|
|
static True test(T);
|
|
|
|
static False test(...);
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCtibleCore<true, T, U>: __OctaCommonType<
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype(__OctaCtibleRef<T>::test(__octa_declval<U>()))
|
2015-04-23 19:38:18 +00:00
|
|
|
>::type {};
|
|
|
|
|
|
|
|
/* scalars and references are not constructible from multiple args */
|
|
|
|
template<typename T, typename U, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCtibleCore<true, T, U, A...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* 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>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCtibleVoidCheck<true, T, A...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
template<typename ...A> struct __OctaCtibleContainsVoid;
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaCtibleContainsVoid<>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
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<
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaRemoveAllExtents<T>::type
|
2015-04-23 19:38:18 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* otherwise array types are not constructible by this syntax */
|
|
|
|
template<typename T, size_t N, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCtibleCore<false, T[N], A...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* incomplete array types are not constructible */
|
|
|
|
template<typename T, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCtibleCore<false, T[], A...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
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,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddLR<typename __OctaAddConst<T>::type>::type
|
2015-04-23 19:38:18 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is move constructible */
|
|
|
|
|
|
|
|
template<typename T> struct IsMoveConstructible: IsConstructible<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddRR<T>::type
|
2015-04-23 19:38:18 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is assignable */
|
|
|
|
|
|
|
|
template<typename T, typename U> typename __OctaSelect2nd<
|
2015-04-24 18:43:20 +00:00
|
|
|
decltype((__octa_declval<T>() = __octa_declval<U>())), True
|
2015-04-23 19:38:18 +00:00
|
|
|
>::type __octa_assign_test(T &&, U &&);
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> False __octa_assign_test(__OctaAny, T &&);
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
template<typename T, typename U, bool = IsVoid<T>::value || IsVoid<U>::value>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaIsAssignable: __OctaCommonType<
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype(__octa_assign_test(__octa_declval<T>(), __octa_declval<U>()))
|
2015-04-23 19:38:18 +00:00
|
|
|
>::type {};
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaIsAssignable<T, U, true>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
struct IsAssignable: __OctaIsAssignable<T, U> {};
|
|
|
|
|
|
|
|
/* is copy assignable */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T> struct IsCopyAssignable: IsAssignable<
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddLR<T>::type,
|
|
|
|
typename __OctaAddLR<typename __OctaAddConst<T>::type>::type
|
2015-04-23 19:38:18 +00:00
|
|
|
> {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
/* is move assignable */
|
|
|
|
|
|
|
|
template<typename T> struct IsMoveAssignable: IsAssignable<
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddLR<T>::type,
|
|
|
|
const typename __OctaAddRR<T>::type
|
2015-04-23 19:38:18 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is destructible */
|
|
|
|
|
|
|
|
template<typename> struct __OctaIsDtibleApply { typedef int type; };
|
2015-04-23 18:26:26 +00:00
|
|
|
|
|
|
|
template<typename T> struct IsDestructorWellformed {
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename TT> static char test(typename __OctaIsDtibleApply<
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype(__octa_declval<TT &>().~TT())
|
2015-04-23 18:26:26 +00:00
|
|
|
>::type);
|
|
|
|
|
|
|
|
template<typename TT> static int test(...);
|
|
|
|
|
|
|
|
static constexpr bool value = (sizeof(test<T>(12)) == sizeof(char));
|
|
|
|
};
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename, bool> struct __OctaDtibleImpl;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct __OctaDtibleImpl<T, false>: IntegralConstant<bool,
|
2015-04-24 18:43:20 +00:00
|
|
|
IsDestructorWellformed<typename __OctaRemoveAllExtents<T>::type>::value
|
2015-04-23 18:26:26 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaDtibleImpl<T, true>: True {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, bool> struct __OctaDtibleFalse;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T> struct __OctaDtibleFalse<T, false>
|
|
|
|
: __OctaDtibleImpl<T, IsReference<T>::value> {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaDtibleFalse<T, true>: False {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct IsDestructible: __OctaDtibleFalse<T, IsFunction<T>::value> {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct IsDestructible<T[] >: False {};
|
|
|
|
template< > struct IsDestructible<void>: False {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* is trivially constructible */
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsTriviallyConstructible: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
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 T>
|
|
|
|
struct IsTriviallyCopyConstructible: IsTriviallyConstructible<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddLR<const T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is trivially move constructible */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyMoveConstructible: IsTriviallyConstructible<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddRR<T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is trivially assignable */
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsTriviallyAssignable: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
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 T>
|
|
|
|
struct IsTriviallyCopyAssignable: IsTriviallyAssignable<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddLR<const T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is trivially move assignable */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyMoveAssignable: IsTriviallyAssignable<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddRR<T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is trivially destructible */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyDestructible: IntegralConstant<bool,
|
|
|
|
__has_trivial_destructor(T)
|
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is nothrow constructible */
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsNothrowConstructible: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
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 T>
|
|
|
|
struct IsNothrowCopyConstructible: IsNothrowConstructible<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddLR<const T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is nothrow move constructible */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsNothrowMoveConstructible: IsNothrowConstructible<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddRR<T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is nothrow assignable */
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct IsNothrowAssignable: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
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 T>
|
|
|
|
struct IsNothrowCopyAssignable: IsNothrowAssignable<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddLR<const T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* is nothrow move assignable */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsNothrowMoveAssignable: IsNothrowAssignable<T,
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaAddRR<T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
|
|
|
|
2015-04-23 18:26:26 +00:00
|
|
|
/* is nothrow destructible */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename, bool> struct __OctaIsNothrowDtible;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct __OctaIsNothrowDtible<T, false>: IntegralConstant<bool,
|
2015-04-23 19:53:05 +00:00
|
|
|
noexcept(__octa_declval<T>().~T())
|
2015-04-23 18:26:26 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename T>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct IsNothrowDestructible: __OctaIsNothrowDtible<T,
|
2015-04-23 18:26:26 +00:00
|
|
|
IsDestructible<T>::value
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename T, size_t N>
|
|
|
|
struct IsNothrowDestructible<T[N]>: IsNothrowDestructible<T> {};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsNothrowDestructible<T &>: IsNothrowDestructible<T> {};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct IsNothrowDestructible<T &&>: IsNothrowDestructible<T> {};
|
|
|
|
|
2015-04-23 00:46:29 +00:00
|
|
|
/* is base of */
|
|
|
|
|
|
|
|
template<typename B, typename D>
|
|
|
|
struct IsBaseOf: IntegralConstant<bool, __is_base_of(B, D)> {};
|
|
|
|
|
2015-04-23 01:39:43 +00:00
|
|
|
/* is convertible */
|
|
|
|
|
|
|
|
template<typename F, typename T, bool = IsVoid<F>::value
|
|
|
|
|| IsFunction<T>::value || IsArray<T>::value
|
2015-04-23 19:38:18 +00:00
|
|
|
> struct __OctaIsConvertible {
|
2015-04-23 01:39:43 +00:00
|
|
|
typedef typename IsVoid<T>::type type;
|
|
|
|
};
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename F, typename T> struct __OctaIsConvertible<F, T, false> {
|
2015-04-23 01:39:43 +00:00
|
|
|
template<typename TT> static void test_f(TT);
|
|
|
|
|
|
|
|
template<typename FF, typename TT,
|
2015-04-23 19:53:05 +00:00
|
|
|
typename = decltype(test_f<TT>(__octa_declval<FF>()))
|
2015-04-24 18:43:20 +00:00
|
|
|
> static True test(int);
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename, typename> static False test(...);
|
2015-04-23 01:39:43 +00:00
|
|
|
|
|
|
|
typedef decltype(test<F, T>(0)) type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename F, typename T>
|
2015-04-23 19:38:18 +00:00
|
|
|
struct IsConvertible: __OctaIsConvertible<F, T>::type {};
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-04-23 00:26:03 +00:00
|
|
|
/* type equality */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename, typename> struct IsSame : False {};
|
|
|
|
template<typename T > struct IsSame<T, T>: True {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
|
|
|
/* extent */
|
|
|
|
|
|
|
|
template<typename T, unsigned I = 0>
|
|
|
|
struct Extent: IntegralConstant<size_t, 0> {};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct Extent<T[], 0>: IntegralConstant<size_t, 0> {};
|
|
|
|
|
|
|
|
template<typename T, unsigned I>
|
|
|
|
struct Extent<T[], I>: IntegralConstant<size_t, Extent<T, I - 1>::value> {};
|
|
|
|
|
|
|
|
template<typename T, size_t N>
|
|
|
|
struct Extent<T[N], 0>: IntegralConstant<size_t, N> {};
|
|
|
|
|
|
|
|
template<typename T, size_t N, unsigned I>
|
|
|
|
struct Extent<T[N], I>: IntegralConstant<size_t, Extent<T, I - 1>::value> {};
|
|
|
|
|
|
|
|
/* rank */
|
|
|
|
|
|
|
|
template<typename T> struct Rank: IntegralConstant<size_t, 0> {};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct Rank<T[]>: IntegralConstant<size_t, Rank<T>::value + 1> {};
|
|
|
|
|
|
|
|
template<typename T, size_t N>
|
|
|
|
struct Rank<T[N]>: IntegralConstant<size_t, Rank<T>::value + 1> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* remove const, volatile, cv */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveConst { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveConst<const T> { typedef T type; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveVolatile { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveVolatile<volatile T> { typedef T type; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaRemoveCV {
|
|
|
|
typedef typename __OctaRemoveVolatile<
|
|
|
|
typename __OctaRemoveConst<T>::type
|
|
|
|
>::type type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using RemoveConst = typename __OctaRemoveConst<T>::type;
|
|
|
|
template<typename T>
|
|
|
|
using RemoveVolatile = typename __OctaRemoveVolatile<T>::type;
|
|
|
|
template<typename T>
|
|
|
|
using RemoveCV = typename __OctaRemoveCV<T>::type;
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* add const, volatile, cv */
|
|
|
|
|
|
|
|
template<typename T, bool = IsReference<T>::value
|
|
|
|
|| IsFunction<T>::value || IsConst<T>::value>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __Octa__OctaAddConst { typedef T type; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __Octa__OctaAddConst<T, false> {
|
2015-04-23 17:47:33 +00:00
|
|
|
typedef const T type;
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaAddConst {
|
|
|
|
typedef typename __Octa__OctaAddConst<T>::type type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, bool = IsReference<T>::value
|
|
|
|
|| IsFunction<T>::value || IsVolatile<T>::value>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __Octa__OctaAddVolatile { typedef T type; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __Octa__OctaAddVolatile<T, false> {
|
2015-04-23 17:47:33 +00:00
|
|
|
typedef volatile T type;
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaAddVolatile {
|
|
|
|
typedef typename __Octa__OctaAddVolatile<T>::type type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaAddCV {
|
|
|
|
typedef typename __OctaAddConst<
|
|
|
|
typename __OctaAddVolatile<T>::type
|
|
|
|
>::type type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using AddConst = typename __OctaAddConst<T>::type;
|
|
|
|
template<typename T>
|
|
|
|
using AddVolatile = typename __OctaAddVolatile<T>::type;
|
|
|
|
template<typename T>
|
|
|
|
using AddCV = typename __OctaAddCV<T>::type;
|
|
|
|
|
2015-04-23 01:16:48 +00:00
|
|
|
/* remove reference */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveReference { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveReference<T &> { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveReference<T &&> { typedef T type; };
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using RemoveReference = typename __OctaRemoveReference<T>::type;
|
2015-04-23 01:16:48 +00:00
|
|
|
|
|
|
|
/* remove pointer */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemovePointer { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemovePointer<T * > { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemovePointer<T * const > { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemovePointer<T * volatile > { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemovePointer<T * const volatile> { typedef T type; };
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using RemovePointer = typename __OctaRemovePointer<T>::type;
|
2015-04-23 01:16:48 +00:00
|
|
|
|
|
|
|
/* add pointer */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaAddPointer {
|
|
|
|
typedef typename __OctaRemoveReference<T>::type *type;
|
2015-04-23 01:16:48 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using AddPointer = typename __OctaAddPointer<T>::type;
|
|
|
|
|
2015-04-18 15:09:08 +00:00
|
|
|
/* add lvalue reference */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaAddLR { typedef T &type; };
|
|
|
|
template<typename T> struct __OctaAddLR<T &> { typedef T &type; };
|
|
|
|
template<typename T> struct __OctaAddLR<T &&> { typedef T &type; };
|
|
|
|
template<> struct __OctaAddLR<void> {
|
2015-04-18 15:09:08 +00:00
|
|
|
typedef void type;
|
|
|
|
};
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaAddLR<const void> {
|
2015-04-18 15:09:08 +00:00
|
|
|
typedef const void type;
|
|
|
|
};
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaAddLR<volatile void> {
|
2015-04-18 15:09:08 +00:00
|
|
|
typedef volatile void type;
|
|
|
|
};
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaAddLR<const volatile void> {
|
2015-04-18 15:09:08 +00:00
|
|
|
typedef const volatile void type;
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using AddLvalueReference = typename __OctaAddLR<T>::type;
|
|
|
|
|
2015-04-18 15:09:08 +00:00
|
|
|
/* add rvalue reference */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaAddRR { typedef T &&type; };
|
|
|
|
template<typename T> struct __OctaAddRR<T &> { typedef T &&type; };
|
|
|
|
template<typename T> struct __OctaAddRR<T &&> { typedef T &&type; };
|
|
|
|
template<> struct __OctaAddRR<void> {
|
2015-04-23 19:53:05 +00:00
|
|
|
typedef void type;
|
|
|
|
};
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaAddRR<const void> {
|
2015-04-23 19:53:05 +00:00
|
|
|
typedef const void type;
|
|
|
|
};
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaAddRR<volatile void> {
|
2015-04-23 19:53:05 +00:00
|
|
|
typedef volatile void type;
|
|
|
|
};
|
2015-04-24 18:43:20 +00:00
|
|
|
template<> struct __OctaAddRR<const volatile void> {
|
2015-04-23 19:53:05 +00:00
|
|
|
typedef const volatile void type;
|
|
|
|
};
|
2015-04-18 15:09:08 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using AddRvalueReference = typename __OctaAddRR<T>::type;
|
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
/* remove extent */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveExtent { typedef T type; };
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaRemoveExtent<T[ ]> { typedef T type; };
|
|
|
|
template<typename T, size_t N>
|
|
|
|
struct __OctaRemoveExtent<T[N]> { typedef T type; };
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using RemoveExtent = typename __OctaRemoveExtent<T>::type;
|
2015-04-22 23:26:29 +00:00
|
|
|
|
|
|
|
/* remove all extents */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaRemoveAllExtents { typedef T type; };
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaRemoveAllExtents<T[]> {
|
|
|
|
typedef typename __OctaRemoveAllExtents<T>::type type;
|
2015-04-22 23:26:29 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T, size_t N> struct __OctaRemoveAllExtents<T[N]> {
|
|
|
|
typedef typename __OctaRemoveAllExtents<T>::type type;
|
2015-04-22 23:26:29 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using RemoveAllExtents = typename __OctaRemoveAllExtents<T>::type;
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* make (un)signed
|
|
|
|
*
|
|
|
|
* this is bad, but i don't see any better way
|
|
|
|
* shamelessly copied from graphitemaster @ neothyne
|
|
|
|
*/
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U> struct __OctaTL {
|
|
|
|
typedef T first;
|
|
|
|
typedef U rest;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
/* not a type */
|
|
|
|
struct __OctaNAT {
|
|
|
|
__OctaNAT() = delete;
|
|
|
|
__OctaNAT(const __OctaNAT &) = delete;
|
|
|
|
__OctaNAT &operator=(const __OctaNAT &) = delete;
|
|
|
|
~__OctaNAT() = delete;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
typedef __OctaTL<schar,
|
|
|
|
__OctaTL<short,
|
|
|
|
__OctaTL<int,
|
|
|
|
__OctaTL<long,
|
|
|
|
__OctaTL<llong, __OctaNAT>>>>> stypes;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
typedef __OctaTL<uchar,
|
|
|
|
__OctaTL<ushort,
|
|
|
|
__OctaTL<uint,
|
|
|
|
__OctaTL<ulong,
|
|
|
|
__OctaTL<ullong, __OctaNAT>>>>> utypes;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, size_t N, bool = (N <= sizeof(typename T::first))>
|
|
|
|
struct __OctaTypeFindFirst;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U, size_t N>
|
|
|
|
struct __OctaTypeFindFirst<__OctaTL<T, U>, N, true> {
|
|
|
|
typedef T type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U, size_t N>
|
|
|
|
struct __OctaTypeFindFirst<__OctaTL<T, U>, N, false> {
|
|
|
|
typedef typename __OctaTypeFindFirst<U, N>::type type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U,
|
2015-04-24 18:43:20 +00:00
|
|
|
bool = IsConst<typename __OctaRemoveReference<T>::type>::value,
|
|
|
|
bool = IsVolatile<typename __OctaRemoveReference<T>::type>::value
|
2015-04-23 19:38:18 +00:00
|
|
|
> struct __OctaApplyCV {
|
|
|
|
typedef U type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaApplyCV<T, U, true, false> { /* const */
|
|
|
|
typedef const U type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaApplyCV<T, U, false, true> { /* volatile */
|
|
|
|
typedef volatile U type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaApplyCV<T, U, true, true> { /* const volatile */
|
|
|
|
typedef const volatile U type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaApplyCV<T &, U, true, false> { /* const */
|
|
|
|
typedef const U &type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaApplyCV<T &, U, false, true> { /* volatile */
|
|
|
|
typedef volatile U &type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaApplyCV<T &, U, true, true> { /* const volatile */
|
|
|
|
typedef const volatile U &type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value>
|
|
|
|
struct __OctaMakeSigned {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, bool = IsIntegral<T>::value || IsEnum<T>::value>
|
|
|
|
struct __OctaMakeUnsigned {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T>
|
|
|
|
struct __OctaMakeSigned<T, true> {
|
|
|
|
typedef typename __OctaTypeFindFirst<stypes, sizeof(T)>::type type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T>
|
|
|
|
struct __OctaMakeUnsigned<T, true> {
|
|
|
|
typedef typename __OctaTypeFindFirst<utypes, sizeof(T)>::type type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<> struct __OctaMakeSigned<bool , true> {};
|
|
|
|
template<> struct __OctaMakeSigned<schar , true> { typedef schar type; };
|
|
|
|
template<> struct __OctaMakeSigned<uchar , true> { typedef schar type; };
|
|
|
|
template<> struct __OctaMakeSigned<short , true> { typedef short type; };
|
|
|
|
template<> struct __OctaMakeSigned<ushort, true> { typedef short type; };
|
|
|
|
template<> struct __OctaMakeSigned<int , true> { typedef int type; };
|
|
|
|
template<> struct __OctaMakeSigned<uint , true> { typedef int type; };
|
|
|
|
template<> struct __OctaMakeSigned<long , true> { typedef long type; };
|
|
|
|
template<> struct __OctaMakeSigned<ulong , true> { typedef long type; };
|
|
|
|
template<> struct __OctaMakeSigned<llong , true> { typedef llong type; };
|
|
|
|
template<> struct __OctaMakeSigned<ullong, true> { typedef llong type; };
|
|
|
|
|
|
|
|
template<> struct __OctaMakeUnsigned<bool , true> {};
|
|
|
|
template<> struct __OctaMakeUnsigned<schar , true> { typedef uchar type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<uchar , true> { typedef uchar type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<short , true> { typedef ushort type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<ushort, true> { typedef ushort type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<int , true> { typedef uint type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<uint , true> { typedef uint type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<long , true> { typedef ulong type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<ulong , true> { typedef ulong type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<llong , true> { typedef ullong type; };
|
|
|
|
template<> struct __OctaMakeUnsigned<ullong, true> { typedef ullong type; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaMakeSignedBase {
|
2015-04-23 19:38:18 +00:00
|
|
|
typedef typename __OctaApplyCV<T,
|
|
|
|
typename __OctaMakeSigned<
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaRemoveCV<T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
>::type
|
|
|
|
>::type type;
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaMakeUnsignedBase {
|
2015-04-23 19:38:18 +00:00
|
|
|
typedef typename __OctaApplyCV<T,
|
|
|
|
typename __OctaMakeUnsigned<
|
2015-04-24 18:43:20 +00:00
|
|
|
typename __OctaRemoveCV<T>::type
|
2015-04-23 17:47:33 +00:00
|
|
|
>::type
|
|
|
|
>::type type;
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using MakeSigned = typename __OctaMakeSignedBase<T>::type;
|
|
|
|
template<typename T>
|
|
|
|
using MakeUnsigned = typename __OctaMakeUnsignedBase<T>::type;
|
|
|
|
|
2015-04-22 23:26:29 +00:00
|
|
|
/* conditional */
|
|
|
|
|
|
|
|
template<bool cond, typename T, typename U>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaConditional {
|
2015-04-22 23:26:29 +00:00
|
|
|
typedef T type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaConditional<false, T, U> {
|
2015-04-22 23:26:29 +00:00
|
|
|
typedef U type;
|
|
|
|
};
|
2015-04-18 15:46:44 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<bool cond, typename T, typename U>
|
|
|
|
using Conditional = typename __OctaConditional<cond, T, U>::type;
|
|
|
|
|
2015-04-18 15:46:44 +00:00
|
|
|
/* result of call at compile time */
|
|
|
|
|
2015-04-23 19:53:05 +00:00
|
|
|
#define __OCTA_FWD(T, v) static_cast<T &&>(v)
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename F, typename ...A>
|
|
|
|
inline auto __octa_rof_invoke(F &&f, A &&...args) ->
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype(__OCTA_FWD(F, f)(__OCTA_FWD(A, args)...)) {
|
|
|
|
return __OCTA_FWD(F, f)(__OCTA_FWD(A, args)...);
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
|
|
|
template<typename B, typename T, typename D>
|
|
|
|
inline auto __octa_rof_invoke(T B::*pmd, D &&ref) ->
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype(__OCTA_FWD(D, ref).*pmd) {
|
|
|
|
return __OCTA_FWD(D, ref).*pmd;
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
|
|
|
template<typename PMD, typename P>
|
|
|
|
inline auto __octa_rof_invoke(PMD &&pmd, P &&ptr) ->
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype((*__OCTA_FWD(P, ptr)).*__OCTA_FWD(PMD, pmd)) {
|
|
|
|
return (*__OCTA_FWD(P, ptr)).*__OCTA_FWD(PMD, pmd);
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
|
|
|
template<typename B, typename T, typename D, typename ...A>
|
|
|
|
inline auto __octa_rof_invoke(T B::*pmf, D &&ref, A &&...args) ->
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype((__OCTA_FWD(D, ref).*pmf)(__OCTA_FWD(A, args)...)) {
|
|
|
|
return (__OCTA_FWD(D, ref).*pmf)(__OCTA_FWD(A, args)...);
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
|
|
|
template<typename PMF, typename P, typename ...A>
|
|
|
|
inline auto __octa_rof_invoke(PMF &&pmf, P &&ptr, A &&...args) ->
|
2015-04-23 19:53:05 +00:00
|
|
|
decltype(((*__OCTA_FWD(P, ptr)).*__OCTA_FWD(PMF, pmf))(__OCTA_FWD(A, args)...)) {
|
|
|
|
return ((*__OCTA_FWD(P, ptr)).*__OCTA_FWD(PMF, pmf))(__OCTA_FWD(A, args)...);
|
2015-04-18 15:46:44 +00:00
|
|
|
}
|
2015-04-23 19:53:05 +00:00
|
|
|
#undef __OCTA_FWD
|
2015-04-18 15:46:44 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename, typename = void>
|
|
|
|
struct __OctaResultOf {};
|
|
|
|
template<typename F, typename ...A>
|
|
|
|
struct __OctaResultOf<F(A...), decltype(void(__octa_rof_invoke(
|
2015-04-23 19:53:05 +00:00
|
|
|
__octa_declval<F>(), __octa_declval<A>()...)))> {
|
|
|
|
using type = decltype(__octa_rof_invoke(__octa_declval<F>(),
|
|
|
|
__octa_declval<A>()...));
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaResultOfBase: __OctaResultOf<T> {};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using ResultOf = typename __OctaResultOfBase<T>::type;
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
/* enable if */
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<bool B, typename T = void> struct __OctaEnableIf {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaEnableIf<true, T> { typedef T type; };
|
|
|
|
|
|
|
|
template<bool B, typename T = void>
|
|
|
|
using EnableIf = typename __OctaEnableIf<B, T>::type;
|
2015-04-22 23:26:29 +00:00
|
|
|
|
|
|
|
/* decay */
|
|
|
|
|
|
|
|
template<typename T>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaDecay {
|
2015-04-22 23:26:29 +00:00
|
|
|
private:
|
2015-04-24 18:43:20 +00:00
|
|
|
typedef typename __OctaRemoveReference<T>::type U;
|
2015-04-22 23:26:29 +00:00
|
|
|
public:
|
2015-04-24 18:43:20 +00:00
|
|
|
typedef typename __OctaConditional<IsArray<U>::value,
|
|
|
|
typename __OctaRemoveExtent<U>::type *,
|
|
|
|
typename __OctaConditional<IsFunction<U>::value,
|
|
|
|
typename __OctaAddPointer<U>::type,
|
|
|
|
typename __OctaRemoveCV<U>::type
|
2015-04-22 23:26:29 +00:00
|
|
|
>::type
|
|
|
|
>::type type;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using Decay = typename __OctaDecay<T>::type;
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* common type */
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename ...T> struct __OctaCommonType;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T> struct __OctaCommonType<T> {
|
|
|
|
typedef __OctaDecay<T> type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T, typename U> struct __OctaCommonType<T, U> {
|
|
|
|
typedef __OctaDecay<decltype(true ? __octa_declval<T>()
|
|
|
|
: __octa_declval<U>())> type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename U, typename ...V>
|
2015-04-24 18:43:20 +00:00
|
|
|
struct __OctaCommonType<T, U, V...> {
|
|
|
|
typedef typename __OctaCommonType<typename __OctaCommonType<T, U>::type,
|
|
|
|
V...>::type type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T, typename U, typename ...V>
|
|
|
|
using CommonType = typename __OctaCommonType<T, U, V...>::type;
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* aligned storage */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<size_t N> struct __OctaAlignedTest {
|
|
|
|
union type {
|
|
|
|
uchar data[N];
|
|
|
|
octa::max_align_t align;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<size_t N, size_t A> struct __OctaAlignedStorage {
|
2015-04-23 17:47:33 +00:00
|
|
|
struct type {
|
|
|
|
alignas(A) uchar data[N];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<size_t N, size_t A
|
|
|
|
= alignof(typename __OctaAlignedTest<N>::type)
|
|
|
|
> using AlignedStorage = typename __OctaAlignedStorage<N, A>::type;
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* aligned union */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<size_t ...N> struct __OctaAlignMax;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<size_t N> struct __OctaAlignMax<N> {
|
|
|
|
static constexpr size_t value = N;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<size_t N1, size_t N2> struct __OctaAlignMax<N1, N2> {
|
|
|
|
static constexpr size_t value = (N1 > N2) ? N1 : N2;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<size_t N1, size_t N2, size_t ...N>
|
|
|
|
struct __OctaAlignMax<N1, N2, N...> {
|
|
|
|
static constexpr size_t value
|
|
|
|
= __OctaAlignMax<__OctaAlignMax<N1, N2>::value, N...>::value;
|
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<size_t N, typename ...T> struct __OctaAlignedUnion {
|
2015-04-23 17:47:33 +00:00
|
|
|
static constexpr size_t alignment_value
|
2015-04-23 19:38:18 +00:00
|
|
|
= __OctaAlignMax<alignof(T)...>::value;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
struct type {
|
2015-04-23 19:38:18 +00:00
|
|
|
alignas(alignment_value) uchar data[__OctaAlignMax<N,
|
2015-04-23 17:47:33 +00:00
|
|
|
sizeof(T)...>::value];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<size_t N, typename ...T>
|
|
|
|
using AlignedUnion = typename __OctaAlignedUnion<N, T...>::type;
|
|
|
|
|
2015-04-23 17:47:33 +00:00
|
|
|
/* underlying type */
|
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T, bool = IsEnum<T>::value> struct __OctaUnderlyingType;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename T> struct __OctaUnderlyingType<T, true> {
|
2015-04-24 18:43:20 +00:00
|
|
|
typedef typename __OctaConditional<IsSigned<T>::value,
|
2015-04-27 17:56:17 +00:00
|
|
|
MakeSigned<T>, MakeUnsigned<T>
|
2015-04-23 17:47:33 +00:00
|
|
|
>::type type;
|
|
|
|
};
|
|
|
|
|
2015-04-24 18:43:20 +00:00
|
|
|
template<typename T>
|
|
|
|
using UnderlyingType = typename __OctaUnderlyingType<T>::type;
|
2015-04-13 21:25:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|