add all remaining traits + cleanup, remove namespace internal etc
parent
a80f535b5d
commit
0c217e2128
|
@ -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.
|
|
@ -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) {
|
||||
|
|
676
octa/traits.h
676
octa/traits.h
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue