libostd/ostd/type_traits.hh

1162 lines
33 KiB
C++
Raw Normal View History

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