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
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
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>
struct FunctorDataManager<T, typename enable_if<!FunctorInPlace<T>
struct FunctorDataManager<T, typename EnableIf<!FunctorInPlace<T>
::value>::type> {
template<typename R, typename ...A>
static R call(const FunctorData &s, A ...args) {

View File

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