2015-04-13 21:25:31 +00:00
|
|
|
/* Type traits for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#ifndef OSTD_TYPE_TRAITS_HH
|
|
|
|
#define OSTD_TYPE_TRAITS_HH
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-04-13 22:04:25 +00:00
|
|
|
#include <stddef.h>
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/types.hh"
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
namespace ostd {
|
2015-06-06 17:22:10 +00:00
|
|
|
/* forward declarations */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-06-04 20:47:30 +00:00
|
|
|
template<typename> struct RemoveCvBase;
|
2015-06-04 20:08:56 +00:00
|
|
|
template<typename> struct AddLr;
|
|
|
|
template<typename> struct AddRr;
|
2015-06-04 20:47:30 +00:00
|
|
|
template<typename> struct AddConstBase;
|
|
|
|
template<typename> struct RemoveReferenceBase;
|
|
|
|
template<typename> struct RemoveAllExtentsBase;
|
2015-06-04 20:08:56 +00:00
|
|
|
|
|
|
|
template<typename ...> struct CommonTypeBase;
|
|
|
|
}
|
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
template<typename> struct IsReference;
|
|
|
|
template<typename> struct IsTriviallyDefaultConstructible;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using RemoveCv = typename detail::RemoveCvBase<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AddLvalueReference = typename detail::AddLr<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AddRvalueReference = typename detail::AddRr<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AddConst = typename detail::AddConstBase<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using RemoveReference = typename detail::RemoveReferenceBase<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using RemoveAllExtents = typename detail::RemoveAllExtentsBase<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T> AddRvalueReference<T> declval_in();
|
2015-06-04 20:08:56 +00:00
|
|
|
}
|
2015-04-23 19:53:05 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* integral constant */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, T val>
|
2015-06-04 20:19:05 +00:00
|
|
|
struct IntegralConstant {
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr T value = val;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-06-07 23:55:08 +00:00
|
|
|
using Value = T;
|
|
|
|
using Type = IntegralConstant<T, val>;
|
2015-04-18 17:32:25 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
constexpr operator Value() const { return value; }
|
|
|
|
constexpr Value operator()() const { return value; }
|
|
|
|
};
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-06-07 23:55:08 +00:00
|
|
|
using True = IntegralConstant<bool, true>;
|
|
|
|
using False = IntegralConstant<bool, false>;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, T val> constexpr T IntegralConstant<T, val>::value;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-07-09 19:23:35 +00:00
|
|
|
/* and */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<bool B, typename ...A> struct AndBase;
|
|
|
|
|
|
|
|
template<typename ...A>
|
|
|
|
struct AndBase<false, A...>: False {};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct AndBase<true>: True {};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct AndBase<true, T>: IntegralConstant<bool, T::Type::value> {};
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
|
|
|
struct AndBase<true, T, A...>: AndBase<T::Type::value, A...> {};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
|
|
|
struct And: detail::AndBase<T::Type::value, A...> {};
|
|
|
|
|
|
|
|
/* or */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<bool B, typename ...A> struct OrBase;
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct OrBase<false>: False {};
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
|
|
|
struct OrBase<false, T, A...>: OrBase<T::Type::value, A...> {};
|
|
|
|
|
|
|
|
template<typename ...A>
|
|
|
|
struct OrBase<true, A...>: True {};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
|
|
|
struct Or: detail::OrBase<T::Type::value, A...> {};
|
|
|
|
|
|
|
|
/* not */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct Not: IntegralConstant<bool, !T::Type::value> {};
|
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is void */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsVoidBase : False {};
|
2015-06-05 22:45:07 +00:00
|
|
|
template< > struct IsVoidBase<void>: True {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsVoid: detail::IsVoidBase<RemoveCv<T>> {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is null pointer */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename> struct IsNullPointerBase : False {};
|
|
|
|
template< > struct IsNullPointerBase<Nullptr>: True {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsNullPointer:
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::IsNullPointerBase<RemoveCv<T>> {};
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is integer */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsIntegralBase: False {};
|
2015-06-04 20:19:05 +00:00
|
|
|
|
|
|
|
template<> struct IsIntegralBase<bool >: True {};
|
|
|
|
template<> struct IsIntegralBase<char >: True {};
|
|
|
|
template<> struct IsIntegralBase<short >: True {};
|
|
|
|
template<> struct IsIntegralBase<int >: True {};
|
|
|
|
template<> struct IsIntegralBase<long >: True {};
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<> struct IsIntegralBase<sbyte >: True {};
|
|
|
|
template<> struct IsIntegralBase<byte >: True {};
|
|
|
|
template<> struct IsIntegralBase<ushort>: True {};
|
|
|
|
template<> struct IsIntegralBase<uint >: True {};
|
|
|
|
template<> struct IsIntegralBase<ulong >: True {};
|
|
|
|
template<> struct IsIntegralBase<llong >: True {};
|
|
|
|
template<> struct IsIntegralBase<ullong>: True {};
|
|
|
|
|
|
|
|
template<> struct IsIntegralBase<Char16>: True {};
|
|
|
|
template<> struct IsIntegralBase<Char32>: True {};
|
|
|
|
template<> struct IsIntegralBase<Wchar >: True {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-05-03 23:00:27 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsIntegral: detail::IsIntegralBase<RemoveCv<T>> {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is floating point */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsFloatingPointBase: False {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-08 20:20:12 +00:00
|
|
|
template<> struct IsFloatingPointBase<float >: True {};
|
|
|
|
template<> struct IsFloatingPointBase<double>: True {};
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<> struct IsFloatingPointBase<ldouble>: True {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsFloatingPoint: detail::IsFloatingPointBase<RemoveCv<T>> {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is array */
|
2015-04-13 22:19:52 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename > struct IsArray : False {};
|
|
|
|
template<typename T > struct IsArray<T[] >: True {};
|
|
|
|
template<typename T, Size N> struct IsArray<T[N]>: True {};
|
2015-04-13 22:19:52 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is pointer */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-06-07 03:10:08 +00:00
|
|
|
template<typename > struct IsPointerBase : False {};
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsPointerBase<T *>: True {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsPointer: detail::IsPointerBase<RemoveCv<T>> {};
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is lvalue reference */
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-06-07 03:10:08 +00:00
|
|
|
template<typename > struct IsLvalueReference : False {};
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsLvalueReference<T &>: True {};
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is rvalue reference */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-07 03:10:08 +00:00
|
|
|
template<typename > struct IsRvalueReference : False {};
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsRvalueReference<T &&>: True {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is enum */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsEnum: IntegralConstant<bool, __is_enum(T)> {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is union */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsUnion: IntegralConstant<bool, __is_union(T)> {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is class */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsClass: IntegralConstant<bool, __is_class(T)> {};
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is function */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
|
|
|
struct FunctionTestDummy {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> char function_test(T *);
|
|
|
|
template<typename T> char function_test(FunctionTestDummy);
|
|
|
|
template<typename T> int function_test(...);
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> T &function_source(int);
|
2015-06-07 03:10:08 +00:00
|
|
|
template<typename T> FunctionTestDummy function_source(...);
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsClass<T>::value ||
|
|
|
|
IsUnion<T>::value ||
|
|
|
|
IsVoid<T>::value ||
|
|
|
|
IsReference<T>::value ||
|
|
|
|
IsNullPointer<T>::value
|
2015-06-04 20:08:56 +00:00
|
|
|
> struct IsFunctionBase: IntegralConstant<bool,
|
2015-06-04 21:57:06 +00:00
|
|
|
sizeof(function_test<T>(function_source<T>(0))) == 1
|
2015-04-23 00:46:29 +00:00
|
|
|
> {};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsFunctionBase<T, true>: False {};
|
2015-06-04 20:08:56 +00:00
|
|
|
} /* namespace detail */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T> struct IsFunction: detail::IsFunctionBase<T> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is arithmetic */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsArithmetic: IntegralConstant<bool,
|
|
|
|
(IsIntegral<T>::value || IsFloatingPoint<T>::value)
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is fundamental */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsFundamental: IntegralConstant<bool,
|
|
|
|
(IsArithmetic<T>::value || IsVoid<T>::value || IsNullPointer<T>::value)
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is compound */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsCompound: IntegralConstant<bool,
|
|
|
|
!IsFundamental<T>::value
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is pointer to member */
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename>
|
2015-06-04 20:19:05 +00:00
|
|
|
struct IsMemberPointerBase: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct IsMemberPointerBase<T U::*>: True {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsMemberPointer: detail::IsMemberPointerBase<RemoveCv<T>> {};
|
2015-04-14 00:12:00 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is pointer to member object */
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename>
|
2015-06-04 20:19:05 +00:00
|
|
|
struct IsMemberObjectPointerBase: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct IsMemberObjectPointerBase<T U::*>: IntegralConstant<bool,
|
2015-07-05 22:59:36 +00:00
|
|
|
!IsFunction<T>::value
|
2015-04-23 01:16:48 +00:00
|
|
|
> {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsMemberObjectPointer:
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::IsMemberObjectPointerBase<RemoveCv<T>> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is pointer to member function */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename>
|
2015-06-04 20:19:05 +00:00
|
|
|
struct IsMemberFunctionPointerBase: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct IsMemberFunctionPointerBase<T U::*>: IntegralConstant<bool,
|
2015-07-05 22:59:36 +00:00
|
|
|
IsFunction<T>::value
|
2015-04-23 17:47:33 +00:00
|
|
|
> {};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsMemberFunctionPointer:
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::IsMemberFunctionPointerBase<RemoveCv<T>> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is reference */
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsReference: IntegralConstant<bool,
|
|
|
|
(IsLvalueReference<T>::value || IsRvalueReference<T>::value)
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-13 22:19:52 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is object */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsObject: IntegralConstant<bool,
|
|
|
|
(!IsFunction<T>::value && !IsVoid<T>::value && !IsReference<T>::value)
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is scalar */
|
2015-04-13 22:04:25 +00:00
|
|
|
|
2015-06-04 21:57:06 +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-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-13 22:04:25 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is abstract */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsAbstract: IntegralConstant<bool, __is_abstract(T)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is const */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-05 22:45:07 +00:00
|
|
|
template<typename > struct IsConst : False {};
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsConst<const T>: True {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is volatile */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-05 22:45:07 +00:00
|
|
|
template<typename > struct IsVolatile : False {};
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsVolatile<volatile T>: True {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is empty */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsEmpty: IntegralConstant<bool, __is_empty(T)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is POD */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsPod: IntegralConstant<bool, __is_pod(T)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is polymorphic */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsPolymorphic: IntegralConstant<bool, __is_polymorphic(T)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is signed */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-07-01 17:51:39 +00:00
|
|
|
namespace detail {
|
|
|
|
template<typename T>
|
|
|
|
struct IsSignedBase: IntegralConstant<bool, T(-1) < T(0)> {};
|
|
|
|
}
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsArithmetic<T>::value>
|
2015-07-01 17:51:39 +00:00
|
|
|
struct IsSigned: False {};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsSigned<T, true>: detail::IsSignedBase<T> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is unsigned */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-07-01 17:51:39 +00:00
|
|
|
namespace detail {
|
|
|
|
template<typename T>
|
|
|
|
struct IsUnsignedBase: IntegralConstant<bool, T(0) < T(-1)> {};
|
|
|
|
}
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsArithmetic<T>::value>
|
2015-07-01 17:51:39 +00:00
|
|
|
struct IsUnsigned: False {};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsUnsigned<T, true>: detail::IsUnsignedBase<T> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is standard layout */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsStandardLayout: IntegralConstant<bool, __is_standard_layout(T)> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is literal type */
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsLiteralType: IntegralConstant<bool, __is_literal_type(T)> {};
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is trivially copyable */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 20:19:05 +00:00
|
|
|
struct IsTriviallyCopyable: IntegralConstant<bool,
|
2015-06-04 21:57:06 +00:00
|
|
|
IsScalar<RemoveAllExtents<T>>::value
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is trivial */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTrivial: IntegralConstant<bool, __is_trivial(T)> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* has virtual destructor */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 20:19:05 +00:00
|
|
|
struct HasVirtualDestructor: IntegralConstant<bool,
|
2015-06-04 21:57:06 +00:00
|
|
|
__has_virtual_destructor(T)
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is constructible */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-07-13 19:08:55 +00:00
|
|
|
#define OSTD_MOVE(v) static_cast<RemoveReference<decltype(v)> &&>(v)
|
2015-04-23 19:53:05 +00:00
|
|
|
|
2015-06-07 23:55:08 +00:00
|
|
|
template<typename, typename T> struct Select2nd { using Type = T; };
|
2015-06-04 20:08:56 +00:00
|
|
|
struct Any { Any(...); };
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A> typename Select2nd<
|
2015-07-13 19:08:55 +00:00
|
|
|
decltype(OSTD_MOVE(T(declval_in<A>()...))), True
|
2015-06-04 21:57:06 +00:00
|
|
|
>::Type is_ctible_test(T &&, A &&...);
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#undef OSTD_MOVE
|
2015-04-23 19:53:05 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename ...A> False is_ctible_test(Any, A &&...);
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<bool, typename T, typename ...A>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct CtibleCore: CommonTypeBase<
|
2015-06-04 21:57:06 +00:00
|
|
|
decltype(is_ctible_test(declval_in<T>(), declval_in<A>()...))
|
2015-05-03 22:50:09 +00:00
|
|
|
>::Type {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* function types are not constructible */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename R, typename ...A1, typename ...A2>
|
|
|
|
struct CtibleCore<false, R(A1...), A2...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* scalars are default constructible, refs are not */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct CtibleCore<true, T>: IsScalar<T> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* scalars and references are constructible from one arg if
|
|
|
|
* implicitly convertible to scalar or reference */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct CtibleRef {
|
2015-06-04 21:57:06 +00:00
|
|
|
static True test(T);
|
2015-06-04 20:08:56 +00:00
|
|
|
static False test(...);
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct CtibleCore<true, T, U>: CommonTypeBase<
|
|
|
|
decltype(CtibleRef<T>::test(declval_in<U>()))
|
2015-05-03 22:50:09 +00:00
|
|
|
>::Type {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* scalars and references are not constructible from multiple args */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U, typename ...A>
|
|
|
|
struct CtibleCore<true, T, U, A...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* treat scalars and refs separately */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<bool, typename T, typename ...A>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct CtibleVoidCheck: CtibleCore<
|
2015-07-05 22:59:36 +00:00
|
|
|
(IsScalar<T>::value || IsReference<T>::value), T, A...
|
2015-04-23 19:38:18 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* if any of T or A is void, IsConstructible should be false */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
|
|
|
struct CtibleVoidCheck<true, T, A...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename ...A> struct CtibleContainsVoid;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
template<> struct CtibleContainsVoid<>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
|
|
|
struct CtibleContainsVoid<T, A...> {
|
2015-07-05 22:59:36 +00:00
|
|
|
static constexpr bool value = IsVoid<T>::value
|
2015-06-04 21:57:06 +00:00
|
|
|
|| CtibleContainsVoid<A...>::value;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* entry point */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct Ctible: CtibleVoidCheck<
|
2015-07-05 22:59:36 +00:00
|
|
|
CtibleContainsVoid<T, A...>::value || IsAbstract<T>::value,
|
2015-06-04 21:57:06 +00:00
|
|
|
T, A...
|
2015-04-23 19:38:18 +00:00
|
|
|
> {};
|
|
|
|
|
|
|
|
/* array types are default constructible if their element type is */
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N>
|
|
|
|
struct CtibleCore<false, T[N]>: Ctible<RemoveAllExtents<T>> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* otherwise array types are not constructible by this syntax */
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N, typename ...A>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct CtibleCore<false, T[N], A...>: False {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* incomplete array types are not constructible */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
|
|
|
struct CtibleCore<false, T[], A...>: False {};
|
2015-06-04 20:08:56 +00:00
|
|
|
} /* namespace detail */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsConstructible: detail::Ctible<T, A...> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is default constructible */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsDefaultConstructible: IsConstructible<T> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is copy constructible */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsCopyConstructible: IsConstructible<T,
|
|
|
|
AddLvalueReference<AddConst<T>>
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is move constructible */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsMoveConstructible: IsConstructible<T,
|
|
|
|
AddRvalueReference<T>
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is assignable */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, typename U> typename detail::Select2nd<
|
2015-06-04 21:57:06 +00:00
|
|
|
decltype((declval_in<T>() = declval_in<U>())), True
|
|
|
|
>::Type assign_test(T &&, U &&);
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> False assign_test(Any, T &&);
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, typename U, bool = IsVoid<T>::value ||
|
|
|
|
IsVoid<U>::value
|
2015-06-04 20:08:56 +00:00
|
|
|
> struct IsAssignableBase: CommonTypeBase<
|
2015-06-04 21:57:06 +00:00
|
|
|
decltype(assign_test(declval_in<T>(), declval_in<U>()))
|
2015-05-03 22:50:09 +00:00
|
|
|
>::Type {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct IsAssignableBase<T, U, true>: False {};
|
2015-06-04 20:08:56 +00:00
|
|
|
} /* namespace detail */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsAssignable: detail::IsAssignableBase<T, U> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is copy assignable */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsCopyAssignable: IsAssignable<
|
|
|
|
AddLvalueReference<T>,
|
|
|
|
AddLvalueReference<AddConst<T>>
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is move assignable */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsMoveAssignable: IsAssignable<
|
|
|
|
AddLvalueReference<T>,
|
|
|
|
const AddRvalueReference<T>
|
2015-06-04 20:19:05 +00:00
|
|
|
> {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is destructible */
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-07 23:55:08 +00:00
|
|
|
template<typename> struct IsDtibleApply { using Type = int; };
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsDestructorWellformed {
|
|
|
|
template<typename TT> static char test(typename IsDtibleApply<
|
2015-07-05 22:59:36 +00:00
|
|
|
decltype(detail::declval_in<TT &>().~TT())
|
2015-05-03 22:50:09 +00:00
|
|
|
>::Type);
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename TT> static int test(...);
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(12)) == sizeof(char));
|
2015-04-23 18:26:26 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
template<typename, bool> struct DtibleImpl;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct DtibleImpl<T, false>: IntegralConstant<bool,
|
|
|
|
IsDestructorWellformed<RemoveAllExtents<T>>::value
|
2015-04-23 18:26:26 +00:00
|
|
|
> {};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct DtibleImpl<T, true>: True {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, bool> struct DtibleFalse;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct DtibleFalse<T, false>
|
2015-07-05 22:59:36 +00:00
|
|
|
: DtibleImpl<T, IsReference<T>::value> {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct DtibleFalse<T, true>: False {};
|
2015-06-04 20:47:30 +00:00
|
|
|
} /* namespace detail */
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsDestructible: detail::DtibleFalse<T, IsFunction<T>::value> {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct IsDestructible<T[]>: False {};
|
2015-06-04 20:47:30 +00:00
|
|
|
template< > struct IsDestructible<void>: False {};
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially constructible */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
2015-06-04 20:47:30 +00:00
|
|
|
struct IsTriviallyConstructible: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyConstructible<T>: IntegralConstant<bool,
|
|
|
|
__has_trivial_constructor(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyConstructible<T, T &>: IntegralConstant<bool,
|
|
|
|
__has_trivial_copy(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyConstructible<T, const T &>: IntegralConstant<bool,
|
|
|
|
__has_trivial_copy(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyConstructible<T, T &&>: IntegralConstant<bool,
|
|
|
|
__has_trivial_copy(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially default constructible */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyDefaultConstructible: IsTriviallyConstructible<T> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially copy constructible */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyCopyConstructible: IsTriviallyConstructible<T,
|
|
|
|
AddLvalueReference<const T>
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially move constructible */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyMoveConstructible: IsTriviallyConstructible<T,
|
|
|
|
AddRvalueReference<T>
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially assignable */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
2015-06-04 20:47:30 +00:00
|
|
|
struct IsTriviallyAssignable: False {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyAssignable<T>: IntegralConstant<bool,
|
|
|
|
__has_trivial_assign(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyAssignable<T, T &>: IntegralConstant<bool,
|
|
|
|
__has_trivial_copy(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyAssignable<T, const T &>: IntegralConstant<bool,
|
|
|
|
__has_trivial_copy(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyAssignable<T, T &&>: IntegralConstant<bool,
|
|
|
|
__has_trivial_copy(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially copy assignable */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyCopyAssignable: IsTriviallyAssignable<T,
|
|
|
|
AddLvalueReference<const T>
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially move assignable */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct IsTriviallyMoveAssignable: IsTriviallyAssignable<T,
|
|
|
|
AddRvalueReference<T>
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially destructible */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 20:47:30 +00:00
|
|
|
struct IsTriviallyDestructible: IntegralConstant<bool,
|
2015-06-04 21:57:06 +00:00
|
|
|
__has_trivial_destructor(T)
|
2015-06-04 20:47:30 +00:00
|
|
|
> {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is base of */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename B, typename D>
|
|
|
|
struct IsBaseOf: IntegralConstant<bool, __is_base_of(B, D)> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is convertible */
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename F, typename T, bool = IsVoid<F>::value
|
|
|
|
|| IsFunction<T>::value || IsArray<T>::value
|
2015-06-04 20:47:30 +00:00
|
|
|
> struct IsConvertibleBase {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = typename IsVoid<T>::Type;
|
2015-04-23 01:39:43 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename F, typename T>
|
|
|
|
struct IsConvertibleBase<F, T, false> {
|
|
|
|
template<typename TT> static void test_f(TT);
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename FF, typename TT,
|
|
|
|
typename = decltype(test_f<TT>(declval_in<FF>()))
|
2015-07-05 22:59:36 +00:00
|
|
|
> static True test(int);
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename, typename> static False test(...);
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = decltype(test<F, T>(0));
|
2015-04-23 01:39:43 +00:00
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename F, typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct IsConvertible: detail::IsConvertibleBase<F, T>::Type {};
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* type equality */
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-05 22:45:07 +00:00
|
|
|
template<typename, typename> struct IsSame : False {};
|
|
|
|
template<typename T > struct IsSame<T, T>: True {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* extent */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, uint I = 0>
|
|
|
|
struct Extent: IntegralConstant<Size, 0> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct Extent<T[], 0>: IntegralConstant<Size, 0> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, uint I>
|
|
|
|
struct Extent<T[], I>: IntegralConstant<Size, Extent<T, I - 1>::value> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N>
|
|
|
|
struct Extent<T[N], 0>: IntegralConstant<Size, N> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N, uint I>
|
|
|
|
struct Extent<T[N], I>: IntegralConstant<Size, Extent<T, I - 1>::value> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* rank */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T> struct Rank: IntegralConstant<Size, 0> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct Rank<T[]>: IntegralConstant<Size, Rank<T>::value + 1> {};
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N>
|
|
|
|
struct Rank<T[N]>: IntegralConstant<Size, Rank<T>::value + 1> {};
|
2015-04-23 00:26:03 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* remove const, volatile, cv */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveConstBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveConstBase<const T> { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveVolatileBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveVolatileBase<volatile T> { using Type = T; };
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using RemoveConst = typename detail::RemoveConstBase<T>::Type;
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using RemoveVolatile = typename detail::RemoveVolatileBase<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 20:47:30 +00:00
|
|
|
struct RemoveCvBase {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = RemoveVolatile<RemoveConst<T>>;
|
2015-05-06 18:52:07 +00:00
|
|
|
};
|
2015-06-04 20:08:56 +00:00
|
|
|
}
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* add const, volatile, cv */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsReference<T>::value
|
|
|
|
|| IsFunction<T>::value || IsConst<T>::value>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct AddConstCore { using Type = T; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct AddConstCore<T, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const T;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct AddConstBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename AddConstCore<T>::Type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsReference<T>::value
|
|
|
|
|| IsFunction<T>::value || IsVolatile<T>::value>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct AddVolatileCore { using Type = T; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct AddVolatileCore<T, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = volatile T;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct AddVolatileBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename AddVolatileCore<T>::Type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AddVolatile = typename detail::AddVolatileBase<T>::Type;
|
2015-05-06 18:52:07 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 20:47:30 +00:00
|
|
|
struct AddCvBase {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = AddConst<AddVolatile<T>>;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AddCv = typename detail::AddCvBase<T>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* remove reference */
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveReferenceBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveReferenceBase<T &> { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveReferenceBase<T &&> { using Type = T; };
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* remove pointer */
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemovePointerBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemovePointerBase<T * > { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemovePointerBase<T * const > { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemovePointerBase<T * volatile > { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemovePointerBase<T * const volatile> { using Type = T; };
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using RemovePointer = typename detail::RemovePointerBase<T>::Type;
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* add pointer */
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct AddPointerBase {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = RemoveReference<T> *;
|
2015-04-23 01:16:48 +00:00
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AddPointer = typename detail::AddPointerBase<T>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* add lvalue reference */
|
2015-04-18 15:09:08 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-07-11 01:28:40 +00:00
|
|
|
template<typename T> struct AddLr { using Type = T &; };
|
|
|
|
template<typename T> struct AddLr<T &> { using Type = T &; };
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddLr<void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = void;
|
2015-04-18 15:09:08 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddLr<const void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const void;
|
2015-04-18 15:09:08 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddLr<volatile void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = volatile void;
|
2015-04-18 15:09:08 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddLr<const volatile void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const volatile void;
|
2015-04-18 15:09:08 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-18 15:09:08 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* add rvalue reference */
|
2015-04-18 15:09:08 +00:00
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
namespace detail {
|
2015-07-11 01:28:40 +00:00
|
|
|
template<typename T> struct AddRr { using Type = T &&; };
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddRr<void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = void;
|
2015-04-23 19:53:05 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddRr<const void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const void;
|
2015-04-23 19:53:05 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddRr<volatile void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = volatile void;
|
2015-04-23 19:53:05 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
template<> struct AddRr<const volatile void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const volatile void;
|
2015-04-23 19:53:05 +00:00
|
|
|
};
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-18 15:09:08 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* remove extent */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveExtentBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveExtentBase<T[ ]> { using Type = T; };
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct RemoveExtentBase<T[N]> { using Type = T; };
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using RemoveExtent = typename detail::RemoveExtentBase<T>::Type;
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* remove all extents */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-06-07 23:55:08 +00:00
|
|
|
template<typename T> struct RemoveAllExtentsBase { using Type = T; };
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct RemoveAllExtentsBase<T[]> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = RemoveAllExtentsBase<T>;
|
2015-04-22 23:26:29 +00:00
|
|
|
};
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N> struct RemoveAllExtentsBase<T[N]> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = RemoveAllExtentsBase<T>;
|
2015-04-22 23:26:29 +00:00
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
/* make (un)signed
|
|
|
|
*
|
|
|
|
* this is bad, but i don't see any better way
|
|
|
|
* shamelessly copied from graphitemaster @ neothyne
|
|
|
|
*/
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U> struct TypeList {
|
2015-06-07 23:55:08 +00:00
|
|
|
using First = T;
|
|
|
|
using Rest = U;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
/* not a type */
|
2015-06-04 20:08:56 +00:00
|
|
|
struct TlNat {
|
|
|
|
TlNat() = delete;
|
|
|
|
TlNat(const TlNat &) = delete;
|
|
|
|
TlNat &operator=(const TlNat &) = delete;
|
|
|
|
~TlNat() = delete;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
using Stypes = TypeList<sbyte,
|
2015-06-07 23:55:08 +00:00
|
|
|
TypeList<short,
|
|
|
|
TypeList<int,
|
|
|
|
TypeList<long,
|
2015-07-05 22:59:36 +00:00
|
|
|
TypeList<llong, TlNat>>>>>;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
using Utypes = TypeList<byte,
|
|
|
|
TypeList<ushort,
|
|
|
|
TypeList<uint,
|
|
|
|
TypeList<ulong,
|
|
|
|
TypeList<ullong, TlNat>>>>>;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, Size N, bool = (N <= sizeof(typename T::First))>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct TypeFindFirst;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, typename U, Size N>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct TypeFindFirst<TypeList<T, U>, N, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = T;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, typename U, Size N>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct TypeFindFirst<TypeList<T, U>, N, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename TypeFindFirst<U, N>::Type;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U,
|
2015-07-05 22:59:36 +00:00
|
|
|
bool = IsConst<RemoveReference<T>>::value,
|
|
|
|
bool = IsVolatile<RemoveReference<T>>::value
|
2015-06-04 20:08:56 +00:00
|
|
|
> struct ApplyCv {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = U;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct ApplyCv<T, U, true, false> { /* const */
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const U;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct ApplyCv<T, U, false, true> { /* volatile */
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = volatile U;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct ApplyCv<T, U, true, true> { /* const volatile */
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const volatile U;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct ApplyCv<T &, U, true, false> { /* const */
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const U &;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct ApplyCv<T &, U, false, true> { /* volatile */
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = volatile U &;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct ApplyCv<T &, U, true, true> { /* const volatile */
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = const volatile U &;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsIntegral<T>::value ||
|
|
|
|
IsEnum<T>::value>
|
|
|
|
struct MakeSignedCore {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename T, bool = IsIntegral<T>::value ||
|
|
|
|
IsEnum<T>::value>
|
|
|
|
struct MakeUnsignedCore {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct MakeSignedCore<T, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename TypeFindFirst<Stypes, sizeof(T)>::Type;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct MakeUnsignedCore<T, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename TypeFindFirst<Utypes, sizeof(T)>::Type;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<> struct MakeSignedCore<bool , true> {};
|
|
|
|
template<> struct MakeSignedCore<short , true> { using Type = short; };
|
|
|
|
template<> struct MakeSignedCore<int , true> { using Type = int; };
|
|
|
|
template<> struct MakeSignedCore<long , true> { using Type = long; };
|
|
|
|
|
|
|
|
template<> struct MakeSignedCore<sbyte , true> { using Type = sbyte; };
|
|
|
|
template<> struct MakeSignedCore<byte , true> { using Type = sbyte; };
|
|
|
|
template<> struct MakeSignedCore<ushort, true> { using Type = short; };
|
|
|
|
template<> struct MakeSignedCore<uint , true> { using Type = int; };
|
|
|
|
template<> struct MakeSignedCore<ulong , true> { using Type = long; };
|
|
|
|
template<> struct MakeSignedCore<llong , true> { using Type = llong; };
|
|
|
|
template<> struct MakeSignedCore<ullong, true> { using Type = llong; };
|
|
|
|
|
|
|
|
template<> struct MakeUnsignedCore<bool , true> {};
|
|
|
|
template<> struct MakeUnsignedCore<short , true> { using Type = ushort; };
|
|
|
|
template<> struct MakeUnsignedCore<int , true> { using Type = uint; };
|
|
|
|
template<> struct MakeUnsignedCore<long , true> { using Type = ulong; };
|
|
|
|
|
|
|
|
template<> struct MakeUnsignedCore<sbyte , true> { using Type = byte; };
|
|
|
|
template<> struct MakeUnsignedCore<byte , true> { using Type = byte; };
|
|
|
|
template<> struct MakeUnsignedCore<ushort, true> { using Type = ushort; };
|
|
|
|
template<> struct MakeUnsignedCore<uint , true> { using Type = uint; };
|
|
|
|
template<> struct MakeUnsignedCore<ulong , true> { using Type = ulong; };
|
|
|
|
template<> struct MakeUnsignedCore<llong , true> { using Type = ullong; };
|
|
|
|
template<> struct MakeUnsignedCore<ullong, true> { using Type = ullong; };
|
2015-06-04 20:08:56 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct MakeSignedBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename ApplyCv<T,
|
2015-07-05 22:59:36 +00:00
|
|
|
typename MakeSignedCore<RemoveCv<T>>::Type
|
2015-06-07 23:55:08 +00:00
|
|
|
>::Type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct MakeUnsignedBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename ApplyCv<T,
|
2015-07-05 22:59:36 +00:00
|
|
|
typename MakeUnsignedCore<RemoveCv<T>>::Type
|
2015-06-07 23:55:08 +00:00
|
|
|
>::Type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
2015-06-04 20:08:56 +00:00
|
|
|
} /* namespace detail */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using MakeSigned = typename detail::MakeSignedBase<T>::Type;
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using MakeUnsigned = typename detail::MakeUnsignedBase<T>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
/* conditional */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<bool _cond, typename T, typename U>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct ConditionalBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = T;
|
2015-04-22 23:26:29 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct ConditionalBase<false, T, U> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = U;
|
2015-04-22 23:26:29 +00:00
|
|
|
};
|
2015-06-04 20:08:56 +00:00
|
|
|
}
|
2015-04-18 15:46:44 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<bool _cond, typename T, typename U>
|
2015-07-05 22:59:36 +00:00
|
|
|
using Conditional = typename detail::ConditionalBase<_cond, T, U>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
/* result of call at compile time */
|
2015-04-18 15:46:44 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-07-13 19:08:55 +00:00
|
|
|
#define OSTD_FWD(T, _v) static_cast<T &&>(_v)
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename F, typename ...A>
|
|
|
|
inline auto rof_invoke(F &&f, A &&...args) ->
|
2015-07-13 19:08:55 +00:00
|
|
|
decltype(OSTD_FWD(F, f)(OSTD_FWD(A, args)...)) {
|
|
|
|
return OSTD_FWD(F, f)(OSTD_FWD(A, args)...);
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename B, typename T, typename D>
|
|
|
|
inline auto rof_invoke(T B::*pmd, D &&ref) ->
|
2015-07-13 19:08:55 +00:00
|
|
|
decltype(OSTD_FWD(D, ref).*pmd) {
|
|
|
|
return OSTD_FWD(D, ref).*pmd;
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename PMD, typename P>
|
|
|
|
inline auto rof_invoke(PMD &&pmd, P &&ptr) ->
|
2015-07-13 19:08:55 +00:00
|
|
|
decltype((*OSTD_FWD(P, ptr)).*OSTD_FWD(PMD, pmd)) {
|
|
|
|
return (*OSTD_FWD(P, ptr)).*OSTD_FWD(PMD, pmd);
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename B, typename T, typename D, typename ...A>
|
|
|
|
inline auto rof_invoke(T B::*pmf, D &&ref, A &&...args) ->
|
2015-07-13 19:08:55 +00:00
|
|
|
decltype((OSTD_FWD(D, ref).*pmf)(OSTD_FWD(A, args)...)) {
|
|
|
|
return (OSTD_FWD(D, ref).*pmf)(OSTD_FWD(A, args)...);
|
2015-04-23 19:38:18 +00:00
|
|
|
}
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename PMF, typename P, typename ...A>
|
|
|
|
inline auto rof_invoke(PMF &&pmf, P &&ptr, A &&...args) ->
|
2015-07-13 19:08:55 +00:00
|
|
|
decltype(((*OSTD_FWD(P, ptr)).*OSTD_FWD(PMF, pmf))
|
|
|
|
(OSTD_FWD(A, args)...)) {
|
|
|
|
return ((*OSTD_FWD(P, ptr)).*OSTD_FWD(PMF, pmf))
|
|
|
|
(OSTD_FWD(A, args)...);
|
2015-04-18 15:46:44 +00:00
|
|
|
}
|
2015-07-13 19:08:55 +00:00
|
|
|
#undef OSTD_FWD
|
2015-04-18 15:46:44 +00:00
|
|
|
|
2015-04-23 19:38:18 +00:00
|
|
|
template<typename, typename = void>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct ResultOfCore {};
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename F, typename ...A>
|
|
|
|
struct ResultOfCore<F(A...), decltype(void(rof_invoke(
|
2015-07-05 22:59:36 +00:00
|
|
|
detail::declval_in<F>(), detail::declval_in<A>()...)))> {
|
|
|
|
using type = decltype(rof_invoke(detail::declval_in<F>(),
|
|
|
|
detail::declval_in<A>()...));
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct ResultOfBase: ResultOfCore<T> {};
|
2015-06-04 20:08:56 +00:00
|
|
|
} /* namespace detail */
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using ResultOf = typename detail::ResultOfBase<T>::Type;
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
/* enable if */
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<bool B, typename T = void> struct EnableIfBase {};
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-07 23:55:08 +00:00
|
|
|
template<typename T> struct EnableIfBase<true, T> { using Type = T; };
|
2015-06-04 20:08:56 +00:00
|
|
|
}
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<bool B, typename T = void>
|
2015-07-05 22:59:36 +00:00
|
|
|
using EnableIf = typename detail::EnableIfBase<B, T>::Type;
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
/* decay */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 20:08:56 +00:00
|
|
|
struct DecayBase {
|
2015-04-22 23:26:29 +00:00
|
|
|
private:
|
2015-07-05 22:59:36 +00:00
|
|
|
using U = RemoveReference<T>;
|
2015-04-22 23:26:29 +00:00
|
|
|
public:
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = Conditional<IsArray<U>::value,
|
|
|
|
RemoveExtent<U> *,
|
|
|
|
Conditional<IsFunction<U>::value,
|
|
|
|
AddPointer<U>, RemoveCv<U>>
|
2015-06-07 23:55:08 +00:00
|
|
|
>;
|
2015-04-22 23:26:29 +00:00
|
|
|
};
|
2015-06-04 20:08:56 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using Decay = typename detail::DecayBase<T>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
/* common type */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename ...T> struct CommonTypeBase;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct CommonTypeBase<T> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = Decay<T>;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U> struct CommonTypeBase<T, U> {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = Decay<decltype(true ? detail::declval_in<T>()
|
|
|
|
: detail::declval_in<U>())>;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U, typename ...V>
|
|
|
|
struct CommonTypeBase<T, U, V...> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename CommonTypeBase<
|
|
|
|
typename CommonTypeBase<T, U>::Type, V...
|
|
|
|
>::Type;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
2015-06-04 20:08:56 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U, typename ...V>
|
2015-07-05 22:59:36 +00:00
|
|
|
using CommonType = typename detail::CommonTypeBase<T, U, V...>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* aligned storage */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N> struct AlignedTest {
|
2015-06-29 22:18:08 +00:00
|
|
|
union Type {
|
2015-07-05 22:59:36 +00:00
|
|
|
byte data[N];
|
|
|
|
MaxAlign align;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N, Size A> struct AlignedStorageBase {
|
2015-06-29 22:18:08 +00:00
|
|
|
struct Type {
|
2015-07-05 22:59:36 +00:00
|
|
|
alignas(A) byte data[N];
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N, Size A
|
|
|
|
= alignof(typename detail::AlignedTest<N>::Type)
|
|
|
|
> using AlignedStorage = typename detail::AlignedStorageBase<N, A>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* aligned union */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size ...N> struct AlignMax;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N> struct AlignMax<N> {
|
|
|
|
static constexpr Size value = N;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N1, Size N2> struct AlignMax<N1, N2> {
|
|
|
|
static constexpr Size value = (N1 > N2) ? N1 : N2;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N1, Size N2, Size ...N>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct AlignMax<N1, N2, N...> {
|
2015-07-05 22:59:36 +00:00
|
|
|
static constexpr Size value
|
2015-06-04 21:57:06 +00:00
|
|
|
= AlignMax<AlignMax<N1, N2>::value, N...>::value;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N, typename ...T> struct AlignedUnionBase {
|
|
|
|
static constexpr Size alignment_value
|
2015-06-04 21:57:06 +00:00
|
|
|
= AlignMax<alignof(T)...>::value;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
|
|
|
struct type {
|
2015-07-05 22:59:36 +00:00
|
|
|
alignas(alignment_value) byte data[AlignMax<N,
|
2015-06-04 21:57:06 +00:00
|
|
|
sizeof(T)...>::value];
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
} /* namespace detail */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N, typename ...T>
|
|
|
|
using AlignedUnion = typename detail::AlignedUnionBase<N, T...>::Type;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* underlying type */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
namespace detail {
|
2015-05-05 18:29:47 +00:00
|
|
|
/* gotta wrap, in a struct otherwise clang ICEs... */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T> struct UnderlyingTypeBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = __underlying_type(T);
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using UnderlyingType = typename detail::UnderlyingTypeBase<T>::Type;
|
2015-07-09 19:23:35 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
} /* namespace ostd */
|
2015-04-13 21:25:31 +00:00
|
|
|
|
|
|
|
#endif
|