2015-04-13 21:25:31 +00:00
|
|
|
/* Type traits for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
2016-09-11 14:26:36 +00:00
|
|
|
* Portions of this file are originally adapted from the libc++ project.
|
2015-04-13 21:25:31 +00:00
|
|
|
*/
|
|
|
|
|
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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
struct RemoveCvBase;
|
|
|
|
template<typename>
|
|
|
|
struct AddLr;
|
|
|
|
template<typename>
|
|
|
|
struct AddRr;
|
|
|
|
template<typename>
|
|
|
|
struct AddConstBase;
|
|
|
|
template<typename>
|
|
|
|
struct RemoveReferenceBase;
|
|
|
|
template<typename>
|
|
|
|
struct RemoveAllExtentsBase;
|
|
|
|
|
|
|
|
template<typename ...>
|
|
|
|
struct CommonTypeBase;
|
2015-06-04 20:08:56 +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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
2016-09-11 18:46:34 +00:00
|
|
|
AddRvalueReference<T> declval_in() noexcept;
|
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>
|
2016-01-16 18:31:44 +00:00
|
|
|
struct Constant {
|
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;
|
2016-01-16 18:31:44 +00:00
|
|
|
using Type = Constant<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
|
|
|
|
2016-01-16 18:33:52 +00:00
|
|
|
template<bool val>
|
|
|
|
using BoolConstant = Constant<bool, val>;
|
|
|
|
|
|
|
|
using True = BoolConstant<true>;
|
|
|
|
using False = BoolConstant<false>;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, T val>
|
|
|
|
constexpr T Constant<T, val>::value;
|
2015-04-13 21:25:31 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
/* type equality */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename, typename>
|
|
|
|
constexpr bool IsSame = false;
|
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsSame<T, T> = true;
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
/* is void */
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsVoid = IsSame<RemoveCv<T>, void>;
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
/* is null pointer */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsNullPointer = IsSame<RemoveCv<T>, Nullptr>;
|
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 {
|
2016-07-31 19:40:25 +00: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;
|
2016-01-14 18:49:38 +00:00
|
|
|
|
2016-07-06 17:10:17 +00:00
|
|
|
#ifndef OSTD_TYPES_CHAR_16_32_NO_BUILTINS
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
constexpr bool IsIntegralBase<Char16> = true;
|
|
|
|
template<>
|
|
|
|
constexpr bool IsIntegralBase<Char32> = true;
|
2016-07-06 17:10:17 +00:00
|
|
|
#endif
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
constexpr bool 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>
|
2016-01-14 18:49:38 +00:00
|
|
|
constexpr bool 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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsFloatingPointBase = false;
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
constexpr bool IsFloatingPointBase<float> = true;
|
|
|
|
template<>
|
|
|
|
constexpr bool IsFloatingPointBase<double> = true;
|
2015-06-08 20:20:12 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
constexpr bool 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>
|
2016-01-14 18:49:38 +00:00
|
|
|
constexpr bool 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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsArray = false;
|
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsArray<T[]> = true;
|
|
|
|
template<typename T, Size N>
|
|
|
|
constexpr bool 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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsPointerBase = false;
|
|
|
|
template<typename T>
|
|
|
|
constexpr bool 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>
|
2016-01-14 18:49:38 +00:00
|
|
|
constexpr bool 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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsLvalueReference = false;
|
|
|
|
template<typename T>
|
|
|
|
constexpr bool 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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsRvalueReference = false;
|
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsRvalueReference<T &&> = true;
|
2016-01-12 21:45:26 +00:00
|
|
|
|
|
|
|
/* is reference */
|
|
|
|
|
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsReference = IsLvalueReference<T> || IsRvalueReference<T>;
|
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
|
|
|
|
2016-01-13 20:40:59 +00:00
|
|
|
template<typename T> constexpr bool IsEnum = __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
|
|
|
|
2016-01-13 20:40:59 +00:00
|
|
|
template<typename T> constexpr bool IsUnion = __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
|
|
|
|
2016-01-13 20:40:59 +00:00
|
|
|
template<typename T> constexpr bool IsClass = __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
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
T &function_source(int);
|
|
|
|
template<typename T>
|
|
|
|
FunctionTestDummy function_source(...);
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
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 00:46:29 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsFunctionBase<T, true> = false;
|
2015-06-04 20:08:56 +00:00
|
|
|
} /* namespace detail */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool 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
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsArithmetic = IsIntegral<T> || IsFloatingPoint<T>;
|
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
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsFundamental = IsArithmetic<T> || IsVoid<T> || IsNullPointer<T>;
|
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
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsCompound = !IsFundamental<T>;
|
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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsMemberPointerBase = false;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool 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>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool 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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsMemberObjectPointerBase = false;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsMemberObjectPointerBase<T U::*> = !IsFunction<T>;
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-23 01:16:48 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsMemberObjectPointer = 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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr bool IsMemberFunctionPointerBase = false;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsMemberFunctionPointerBase<T U::*> = IsFunction<T>;
|
2015-06-04 20:19:05 +00:00
|
|
|
}
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsMemberFunctionPointer = detail::IsMemberFunctionPointerBase<RemoveCv<T>>;
|
2015-04-13 22:19:52 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
/* internal member traits, from libc++ */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename MP, bool IsMemberPtr, bool IsMemberObjectPtr>
|
|
|
|
struct MemberPointerTraitsBase {};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...), true, false> {
|
|
|
|
using Class = C;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A..., ...), true, false> {
|
|
|
|
using Class = C;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) const, true, false> {
|
|
|
|
using Class = C const;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A..., ...) const, true, false> {
|
|
|
|
using Class = C const;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) volatile, true, false> {
|
|
|
|
using Class = C volatile;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A..., ...) volatile, true, false> {
|
|
|
|
using Class = C volatile;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) const volatile, true, false> {
|
|
|
|
using Class = C const volatile;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<
|
|
|
|
R (C::*)(A..., ...) const volatile, true, false
|
|
|
|
> {
|
|
|
|
using Class = C const volatile;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) &, true, false> {
|
|
|
|
using Class = C &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A..., ...) &, true, false> {
|
|
|
|
using Class = C &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) const &, true, false> {
|
|
|
|
using Class = C const &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A..., ...) const &, true, false> {
|
|
|
|
using Class = C const &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) volatile &, true, false> {
|
|
|
|
using Class = C volatile &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<
|
|
|
|
R (C::*)(A..., ...) volatile &, true, false
|
|
|
|
> {
|
|
|
|
using Class = C volatile &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<
|
|
|
|
R (C::*)(A...) const volatile &, true, false
|
|
|
|
> {
|
|
|
|
using Class = C const volatile &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<
|
|
|
|
R (C::*)(A..., ...) const volatile &, true, false
|
|
|
|
> {
|
|
|
|
using Class = C const volatile &;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) &&, true, false> {
|
|
|
|
using Class = C &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A..., ...) &&, true, false> {
|
|
|
|
using Class = C &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) const &&, true, false> {
|
|
|
|
using Class = C const &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A..., ...) const &&, true, false> {
|
|
|
|
using Class = C const &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<R (C::*)(A...) volatile &&, true, false> {
|
|
|
|
using Class = C volatile &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<
|
|
|
|
R (C::*)(A..., ...) volatile &&, true, false
|
|
|
|
> {
|
|
|
|
using Class = C volatile &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<
|
|
|
|
R (C::*)(A...) const volatile &&, true, false
|
|
|
|
> {
|
|
|
|
using Class = C const volatile &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class R, class C, class ...A>
|
|
|
|
struct MemberPointerTraitsBase<
|
|
|
|
R (C::*)(A..., ...) const volatile &&, true, false
|
|
|
|
> {
|
|
|
|
using Class = C const volatile &&;
|
|
|
|
using Result = R;
|
|
|
|
using Func = R(A..., ...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename R, typename C>
|
|
|
|
struct MemberPointerTraitsBase<R C::*, false, true> {
|
|
|
|
using Class = C;
|
|
|
|
using Result = R;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename MP>
|
|
|
|
using MemberPointerClass = typename MemberPointerTraitsBase<
|
|
|
|
RemoveCv<MP>, IsMemberFunctionPointer<MP>, IsMemberObjectPointer<MP>
|
|
|
|
>::Class;
|
|
|
|
|
|
|
|
template<typename MP>
|
|
|
|
using MemberPointerResult = typename MemberPointerTraitsBase<
|
|
|
|
RemoveCv<MP>, IsMemberFunctionPointer<MP>, IsMemberObjectPointer<MP>
|
|
|
|
>::Result;
|
|
|
|
|
|
|
|
template<typename MP>
|
|
|
|
using MemberPointerFunc = typename MemberPointerTraitsBase<
|
|
|
|
RemoveCv<MP>, IsMemberFunctionPointer<MP>, IsMemberObjectPointer<MP>
|
|
|
|
>::Func;
|
|
|
|
} /* namespace detail */
|
|
|
|
|
2015-06-04 20:19:05 +00:00
|
|
|
/* is object */
|
2015-04-13 21:56:02 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsObject = !IsFunction<T> && !IsVoid<T> && !IsReference<T>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsScalar =
|
|
|
|
IsMemberPointer<T> || IsPointer<T> || IsEnum<T> ||
|
|
|
|
IsNullPointer <T> || IsArithmetic<T>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsAbstract = __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
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-06-23 18:18:35 +00:00
|
|
|
constexpr bool IsConst = IsSame<T, T const>;
|
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
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-06-23 18:18:35 +00:00
|
|
|
constexpr bool IsVolatile = IsSame<T, T volatile>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsEmpty = __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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsPod = __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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsPolymorphic = __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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsSignedCore = T(-1) < T(0);
|
2016-01-12 21:45:26 +00:00
|
|
|
|
|
|
|
template<typename T, bool = IsArithmetic<T>>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsSignedBase = false;
|
2015-07-01 17:51:39 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsSignedBase<T, true> = detail::IsSignedCore<T>;
|
2016-01-12 21:45:26 +00:00
|
|
|
}
|
2015-07-01 17:51:39 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsSigned = 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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsUnsignedCore = T(0) < T(-1);
|
2016-01-12 21:45:26 +00:00
|
|
|
|
|
|
|
template<typename T, bool = IsArithmetic<T>>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsUnsignedBase = false;
|
2015-07-01 17:51:39 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsUnsignedBase<T, true> = detail::IsUnsignedCore<T>;
|
2016-01-12 21:45:26 +00:00
|
|
|
}
|
2015-07-01 17:51:39 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr bool IsUnsigned = 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>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsStandardLayout = __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>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsLiteralType = __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>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsTriviallyCopyable = IsScalar<RemoveAllExtents<T>>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsTrivial = __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>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool HasVirtualDestructor = __has_virtual_destructor(T);
|
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
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
|
2016-07-31 19:40:25 +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>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool CtibleCore =
|
|
|
|
CommonTypeBase<
|
|
|
|
decltype(is_ctible_test(declval_in<T>(), declval_in<A>()...))
|
|
|
|
>::Type::value;
|
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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool CtibleCore<true, T, U> = CommonTypeBase<
|
2015-06-04 21:57:06 +00:00
|
|
|
decltype(CtibleRef<T>::test(declval_in<U>()))
|
2016-01-14 21:16:42 +00:00
|
|
|
>::Type::value;
|
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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool CtibleVoidCheck =
|
|
|
|
CtibleCore<(IsScalar<T> || IsReference<T>), 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool CtibleVoidCheck<true, T, A...> = false;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename ...A>
|
|
|
|
constexpr bool CtibleContainsVoid = false;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
constexpr bool CtibleContainsVoid<> = false;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool CtibleContainsVoid<T, A...> =
|
|
|
|
IsVoid<T> || CtibleContainsVoid<A...>;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
|
|
|
/* entry point */
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename ...A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool Ctible =
|
|
|
|
CtibleVoidCheck<CtibleContainsVoid<T, A...> || IsAbstract<T>, 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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
|
|
|
|
2016-01-12 22:09:40 +00:00
|
|
|
template<typename T>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool 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
|
|
|
|
2016-01-12 22:09:40 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsCopyConstructible =
|
|
|
|
IsConstructible<T, AddLvalueReference<AddConst<T>>>;
|
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
|
|
|
|
2016-01-12 22:09:40 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsMoveConstructible =
|
|
|
|
IsConstructible<T, AddRvalueReference<T>>;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2016-07-03 00:39:13 +00:00
|
|
|
/* is nothrow constructible */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<bool, bool, typename T, typename ...A>
|
|
|
|
constexpr bool NothrowCtibleCore = false;
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool NothrowCtibleCore<true, false, T, A...> =
|
|
|
|
noexcept(T(declval_in<A>()...));
|
2016-07-03 00:39:13 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
void implicit_conv_to(T) noexcept {}
|
2016-07-03 00:39:13 +00:00
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool NothrowCtibleCore<true, true, T, A> =
|
|
|
|
noexcept(ostd::detail::implicit_conv_to<T>(declval_in<A>()));
|
2016-07-03 00:39:13 +00:00
|
|
|
|
|
|
|
template<typename T, bool R, typename ...A>
|
|
|
|
constexpr bool NothrowCtibleCore<false, R, T, A...> = false;
|
|
|
|
} /* namespace detail */
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, typename ...A> constexpr bool IsNothrowConstructible =
|
|
|
|
detail::NothrowCtibleCore<IsConstructible<T, A...>, IsReference<T>, T, A...>;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, Size N> constexpr bool IsNothrowConstructible<T[N]> =
|
|
|
|
detail::NothrowCtibleCore<IsConstructible<T>, IsReference<T>, T>;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
|
|
|
/* is nothrow default constructible */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsNothrowDefaultConstructible = IsNothrowConstructible<T>;
|
|
|
|
|
|
|
|
/* is nothrow copy constructible */
|
|
|
|
|
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsNothrowCopyConstructible =
|
|
|
|
IsNothrowConstructible<T, AddLvalueReference<AddConst<T>>>;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
|
|
|
/* is nothrow move constructible */
|
|
|
|
|
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsNothrowMoveConstructible =
|
|
|
|
IsNothrowConstructible<T, AddRvalueReference<T>>;
|
2016-07-03 00:39:13 +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 {
|
2016-07-31 19:40:25 +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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
False assign_test(Any, T &&);
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T, typename U, bool = IsVoid<T> || IsVoid<U>>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool IsAssignableBase = CommonTypeBase<
|
2015-06-04 21:57:06 +00:00
|
|
|
decltype(assign_test(declval_in<T>(), declval_in<U>()))
|
2016-01-14 21:16:42 +00:00
|
|
|
>::Type::value;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool 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
|
|
|
|
2016-01-12 22:09:40 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsCopyAssignable =
|
|
|
|
IsAssignable<AddLvalueReference<T>, AddLvalueReference<AddConst<T>>>;
|
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
|
|
|
|
2016-01-12 22:09:40 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsMoveAssignable =
|
|
|
|
IsAssignable<AddLvalueReference<T>, AddRvalueReference<T> const>;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2016-07-03 00:39:13 +00:00
|
|
|
/* is nothrow assignable */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<bool, typename T, typename A>
|
|
|
|
constexpr bool NothrowAssignableCore = false;
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
|
|
|
constexpr bool NothrowAssignableCore<false, T, A> = false;
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool NothrowAssignableCore<true, T, A> =
|
|
|
|
noexcept(declval_in<T>() = declval_in<A>());
|
2016-07-03 00:39:13 +00:00
|
|
|
}
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, typename A> constexpr bool IsNothrowAssignable =
|
|
|
|
detail::NothrowAssignableCore<IsAssignable<T, A>, T, A>;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
|
|
|
/* is nothrow copy assignable */
|
|
|
|
|
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsNothrowCopyAssignable =
|
|
|
|
IsNothrowAssignable<AddLvalueReference<T>, AddLvalueReference<AddConst<T>>>;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
|
|
|
/* is nothrow move assignable */
|
|
|
|
|
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsNothrowMoveAssignable =
|
|
|
|
IsNothrowAssignable<AddLvalueReference<T>, AddRvalueReference<T>>;
|
2016-07-03 00:39:13 +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 {
|
2016-07-31 19:40:25 +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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
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
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename, bool>
|
|
|
|
constexpr bool DtibleImpl = false;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool DtibleImpl<T, false> =
|
|
|
|
IsDestructorWellformed<RemoveAllExtents<T>>::value;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool DtibleImpl<T, true> = true;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, bool>
|
|
|
|
constexpr bool DtibleFalse = false;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool DtibleFalse<T, false> = DtibleImpl<T, IsReference<T>>;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool DtibleFalse<T, true> = false;
|
2016-01-13 18:09:21 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool IsDestructibleBase = detail::DtibleFalse<T, IsFunction<T>>;
|
2016-01-13 18:09:21 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsDestructibleBase<T[]> = false;
|
|
|
|
template<>
|
|
|
|
constexpr bool IsDestructibleBase<void> = 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>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool IsDestructible = detail::IsDestructibleBase<T>;
|
2015-04-23 18:26:26 +00:00
|
|
|
|
2016-07-03 00:39:13 +00:00
|
|
|
/* is nothrow destructible */
|
|
|
|
|
|
|
|
namespace detail {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<bool, typename>
|
|
|
|
constexpr bool NothrowDtibleCore = false;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool NothrowDtibleCore<false, T> = false;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool NothrowDtibleCore<true, T> = noexcept(declval_in<T>().~T());
|
2016-07-03 00:39:13 +00:00
|
|
|
}
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsNothrowDestructible = detail::NothrowDtibleCore<IsDestructible<T>, T>;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, Size N>
|
|
|
|
constexpr bool IsNothrowDestructible<T[N]> = IsNothrowDestructible<T>;
|
2016-07-03 00:39:13 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* is trivially constructible */
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
namespace detail {
|
|
|
|
template<typename T, typename ...A>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool IsTriviallyConstructibleBase = false;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyConstructibleBase<T> =
|
|
|
|
__has_trivial_constructor(T);
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyConstructibleBase<T, T &> = __has_trivial_copy(T);
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyConstructibleBase<T, T const &> =
|
|
|
|
__has_trivial_copy(T);
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyConstructibleBase<T, T &&> = __has_trivial_copy(T);
|
2016-01-13 18:09:21 +00:00
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyConstructible =
|
|
|
|
detail::IsTriviallyConstructibleBase<T, A...>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T> constexpr bool 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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T> constexpr bool IsTriviallyCopyConstructible =
|
|
|
|
IsTriviallyConstructible<T, AddLvalueReference<T const>>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T> constexpr bool IsTriviallyMoveConstructible =
|
|
|
|
IsTriviallyConstructible<T, AddRvalueReference<T>>;
|
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
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
namespace detail {
|
|
|
|
template<typename T, typename ...A>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr bool IsTriviallyAssignableBase = false;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyAssignableBase<T> = __has_trivial_assign(T);
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyAssignableBase<T, T &> = __has_trivial_copy(T);
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyAssignableBase<T, T const &> = __has_trivial_copy(T);
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyAssignableBase<T, T &&> = __has_trivial_copy(T);
|
2016-01-13 18:09:21 +00:00
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool IsTriviallyAssignable = detail::IsTriviallyAssignableBase<T>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsTriviallyCopyAssignable =
|
|
|
|
IsTriviallyAssignable<T, AddLvalueReference<T const>>;
|
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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool IsTriviallyMoveAssignable =
|
|
|
|
IsTriviallyAssignable<T, AddRvalueReference<T>>;
|
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>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsTriviallyDestructible = __has_trivial_destructor(T);
|
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>
|
2016-01-13 20:40:59 +00:00
|
|
|
constexpr bool IsBaseOf = __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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<
|
|
|
|
typename F, typename T, bool =
|
|
|
|
IsVoid<F> || IsFunction<T> || IsArray<T>
|
|
|
|
>
|
|
|
|
struct IsConvertibleBase {
|
2016-01-20 18:42:29 +00:00
|
|
|
static constexpr bool value = IsVoid<T>;
|
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> {
|
2016-07-31 19:40:25 +00:00
|
|
|
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>()))
|
2016-07-31 19:40:25 +00:00
|
|
|
>
|
|
|
|
static True test(int);
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename, typename>
|
|
|
|
static False test(...);
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2016-01-20 18:42:29 +00:00
|
|
|
static constexpr bool value = decltype(test<F, T>(0))::value;
|
2015-04-23 01:39:43 +00:00
|
|
|
};
|
2015-06-04 20:47:30 +00:00
|
|
|
}
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename F, typename T>
|
|
|
|
constexpr bool IsConvertible = detail::IsConvertibleBase<F, T>::value;
|
2015-04-23 01:39:43 +00:00
|
|
|
|
2015-06-04 20:47:30 +00:00
|
|
|
/* extent */
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
namespace detail {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename, uint>
|
|
|
|
constexpr Size ExtentBase = 0;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr Size ExtentBase<T[], 0> = 0;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T, uint I>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr Size ExtentBase<T[], I> = detail::ExtentBase<T, I - 1>;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T, Size N>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr Size ExtentBase<T[N], 0> = N;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
template<typename T, Size N, uint I>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr Size ExtentBase<T[N], I> = detail::ExtentBase<T, I - 1>;
|
2016-01-13 18:09:21 +00:00
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
template<typename T, uint I = 0>
|
2016-01-14 19:03:22 +00:00
|
|
|
constexpr Size Extent = detail::ExtentBase<T, I>;
|
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
|
|
|
|
2016-01-13 18:09:21 +00:00
|
|
|
namespace detail {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename>
|
|
|
|
constexpr Size RankBase = 0;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-14 19:03:22 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr Size RankBase<T[]> = detail::RankBase<T> + 1;
|
2015-04-23 00:46:29 +00:00
|
|
|
|
2016-01-14 19:03:22 +00:00
|
|
|
template<typename T, Size N>
|
|
|
|
constexpr Size RankBase<T[N]> = detail::RankBase<T> + 1;
|
2016-01-13 18:09:21 +00:00
|
|
|
}
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr Size Rank = detail::RankBase<T>;
|
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>
|
2016-07-31 19:40:25 +00:00
|
|
|
struct RemoveConstBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-06-23 18:18:35 +00:00
|
|
|
struct RemoveConstBase<T const> { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
|
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
struct RemoveVolatileBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-06-23 18:18:35 +00:00
|
|
|
struct RemoveVolatileBase<T volatile> { 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 {
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T, bool = IsReference<T> || IsFunction<T> || IsConst<T>>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct AddConstCore { using Type = T; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct AddConstCore<T, false> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = T const;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
};
|
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T, bool = IsReference<T> || IsFunction<T> || IsVolatile<T>>
|
2015-06-07 23:55:08 +00:00
|
|
|
struct AddVolatileCore { using Type = T; };
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct AddVolatileCore<T, false> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = T volatile;
|
2015-04-23 17:47:33 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +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>
|
2016-07-31 19:40:25 +00:00
|
|
|
struct RemoveReferenceBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +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>
|
2016-07-31 19:40:25 +00:00
|
|
|
struct RemovePointerBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
struct RemovePointerBase<T *> { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
struct RemovePointerBase<T * const> { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +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 {
|
2016-07-31 19:40:25 +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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct AddLr { using Type = T &; };
|
|
|
|
template<typename T>
|
|
|
|
struct AddLr<T &> { using Type = T &; };
|
|
|
|
template<>
|
|
|
|
struct AddLr<void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = void;
|
2015-04-18 15:09:08 +00:00
|
|
|
};
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
struct AddLr<void const> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = void const;
|
2015-04-18 15:09:08 +00:00
|
|
|
};
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
struct AddLr<void volatile> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = void volatile;
|
2015-04-18 15:09:08 +00:00
|
|
|
};
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
struct AddLr<void const volatile> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = void const volatile;
|
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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct AddRr { using Type = T &&; };
|
|
|
|
template<>
|
|
|
|
struct AddRr<void> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = void;
|
2015-04-23 19:53:05 +00:00
|
|
|
};
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
struct AddRr<void const> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = void const;
|
2015-04-23 19:53:05 +00:00
|
|
|
};
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
struct AddRr<void volatile> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = void volatile;
|
2015-04-23 19:53:05 +00:00
|
|
|
};
|
2016-07-31 19:40:25 +00:00
|
|
|
template<>
|
|
|
|
struct AddRr<void const volatile> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = void const volatile;
|
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>
|
2016-07-31 19:40:25 +00:00
|
|
|
struct RemoveExtentBase { using Type = T; };
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct RemoveAllExtentsBase { using Type = T; };
|
2015-04-22 23:26:29 +00:00
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +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 {
|
2016-07-31 19:40:25 +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;
|
2016-06-23 18:18:35 +00:00
|
|
|
TlNat(TlNat const &) = delete;
|
|
|
|
TlNat &operator=(TlNat const &) = delete;
|
2015-06-04 20:08:56 +00:00
|
|
|
~TlNat() = delete;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
using Stypes =
|
|
|
|
TypeList<
|
|
|
|
sbyte, TypeList<
|
|
|
|
short, TypeList<
|
|
|
|
int, TypeList<
|
|
|
|
long, TypeList<llong, TlNat>
|
|
|
|
>
|
|
|
|
>
|
|
|
|
>
|
|
|
|
>;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<
|
|
|
|
typename T, typename U,
|
2016-01-12 21:45:26 +00:00
|
|
|
bool = IsConst<RemoveReference<T>>,
|
|
|
|
bool = IsVolatile<RemoveReference<T>>
|
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 */
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = U const;
|
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 */
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = U volatile;
|
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 */
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = U const volatile;
|
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 */
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = U const &;
|
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 */
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = U volatile &;
|
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 */
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = U const volatile &;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T, bool = IsIntegral<T> || IsEnum<T>>
|
2015-07-05 22:59:36 +00:00
|
|
|
struct MakeSignedCore {};
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-01-12 21:45:26 +00:00
|
|
|
template<typename T, bool = IsIntegral<T> || IsEnum<T>>
|
2015-07-05 22:59:36 +00:00
|
|
|
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
|
|
|
|
2016-07-31 19:40:25 +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; };
|
|
|
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
/* enable if */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<bool B, typename T = void>
|
|
|
|
struct EnableIfBase {};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct EnableIfBase<true, T> { using Type = T; };
|
|
|
|
}
|
|
|
|
|
|
|
|
template<bool B, typename T = void>
|
|
|
|
using EnableIf = typename detail::EnableIfBase<B, T>::Type;
|
|
|
|
|
|
|
|
/* result of call at compile time, from libc++ */
|
2015-04-18 15:46:44 +00:00
|
|
|
|
2015-06-04 20:08:56 +00:00
|
|
|
namespace detail {
|
2016-09-11 14:26:36 +00:00
|
|
|
struct InvokeNat {
|
|
|
|
InvokeNat() = delete;
|
|
|
|
InvokeNat(InvokeNat const &) = delete;
|
|
|
|
InvokeNat &operator=(InvokeNat const &) = delete;
|
|
|
|
~InvokeNat() = delete;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct InvokeAny { InvokeAny(...); };
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#define OSTD_FWD(T, _v) static_cast<T &&>(_v)
|
2016-09-11 14:26:36 +00:00
|
|
|
template<typename ...A>
|
2016-09-11 17:57:42 +00:00
|
|
|
inline auto func_invoke(InvokeAny, A &&...) -> InvokeNat;
|
2016-09-11 14:26:36 +00:00
|
|
|
|
2016-09-11 17:57:42 +00:00
|
|
|
/* forward declarations, later defined in functional */
|
2016-09-11 14:26:36 +00:00
|
|
|
template<
|
|
|
|
typename F, typename T, typename ...A,
|
|
|
|
typename = EnableIf<
|
|
|
|
IsMemberFunctionPointer<RemoveReference<F>> &&
|
|
|
|
IsBaseOf<
|
|
|
|
RemoveReference<MemberPointerClass<RemoveReference<F>>>,
|
|
|
|
RemoveReference<T>
|
|
|
|
>
|
|
|
|
>
|
|
|
|
>
|
2016-09-11 17:57:42 +00:00
|
|
|
inline auto func_invoke(F &&f, T &&v, A &&...args) ->
|
|
|
|
decltype((OSTD_FWD(T, v).*f)(OSTD_FWD(A, args)...))
|
|
|
|
{
|
|
|
|
return (OSTD_FWD(T, v).*f)(OSTD_FWD(A, args)...);
|
|
|
|
}
|
2016-09-11 14:26:36 +00:00
|
|
|
|
|
|
|
template<
|
|
|
|
typename F, typename T, typename ...A,
|
|
|
|
typename = EnableIf<
|
|
|
|
IsMemberFunctionPointer<RemoveReference<F>> &&
|
|
|
|
IsBaseOf<
|
|
|
|
RemoveReference<MemberPointerClass<RemoveReference<F>>>,
|
|
|
|
RemoveReference<T>
|
|
|
|
>
|
|
|
|
>
|
|
|
|
>
|
2016-09-11 17:57:42 +00:00
|
|
|
inline auto func_invoke(F &&f, T &&v, A &&...args) ->
|
|
|
|
decltype(((*OSTD_FWD(T, v)).*f)(OSTD_FWD(A, args)...))
|
|
|
|
{
|
|
|
|
return ((*OSTD_FWD(T, v)).*f)(OSTD_FWD(A, args)...);
|
|
|
|
}
|
2016-09-11 14:26:36 +00:00
|
|
|
|
|
|
|
template<
|
|
|
|
typename F, typename T,
|
|
|
|
typename = EnableIf<
|
|
|
|
IsMemberObjectPointer<RemoveReference<F>> &&
|
|
|
|
IsBaseOf<
|
|
|
|
RemoveReference<MemberPointerClass<RemoveReference<F>>>,
|
|
|
|
RemoveReference<T>
|
|
|
|
>
|
|
|
|
>
|
|
|
|
>
|
2016-09-11 17:57:42 +00:00
|
|
|
inline auto func_invoke(F &&f, T &&v) -> decltype(OSTD_FWD(T, v).*f) {
|
|
|
|
return OSTD_FWD(T, v).*f;
|
|
|
|
}
|
2016-09-11 14:26:36 +00:00
|
|
|
|
|
|
|
template<
|
|
|
|
typename F, typename T,
|
|
|
|
typename = EnableIf<
|
|
|
|
IsMemberObjectPointer<RemoveReference<F>> &&
|
|
|
|
IsBaseOf<
|
|
|
|
RemoveReference<MemberPointerClass<RemoveReference<F>>>,
|
|
|
|
RemoveReference<T>
|
|
|
|
>
|
|
|
|
>
|
|
|
|
>
|
2016-09-11 17:57:42 +00:00
|
|
|
inline auto func_invoke(F &&f, T &&v) -> decltype((*OSTD_FWD(T, v)).*f) {
|
|
|
|
return (*OSTD_FWD(T, v)).*f;
|
|
|
|
}
|
2016-09-11 14:26:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename F, typename ...A>
|
2016-09-11 17:57:42 +00:00
|
|
|
inline auto func_invoke(F &&f, A &&...args) ->
|
|
|
|
decltype(OSTD_FWD(F, f)(OSTD_FWD(A, args)...))
|
|
|
|
{
|
|
|
|
return OSTD_FWD(F, f)(OSTD_FWD(A, args)...);
|
|
|
|
}
|
2015-07-13 19:08:55 +00:00
|
|
|
#undef OSTD_FWD
|
2015-04-18 15:46:44 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename F, typename ...A>
|
2016-09-11 14:26:36 +00:00
|
|
|
struct FuncInvokableBase {
|
|
|
|
using Type = decltype(
|
|
|
|
func_invoke(declval_in<F>(), declval_in<A>()...)
|
|
|
|
);
|
|
|
|
static constexpr bool value = !IsSame<Type, InvokeNat>;
|
2015-04-23 19:38:18 +00:00
|
|
|
};
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
template<typename F, typename ...A>
|
|
|
|
constexpr bool IsInvokable = FuncInvokableBase<F, A...>::value;
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
template<bool I, typename F, typename ...A>
|
|
|
|
struct InvokeOfBase {};
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
template<typename F, typename ...A>
|
|
|
|
struct InvokeOfBase<true, F, A...> {
|
|
|
|
using Type = typename FuncInvokableBase<F, A...>::Type;
|
|
|
|
};
|
2015-04-21 22:54:09 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
template<typename F, typename ...A>
|
|
|
|
using InvokeOf = typename InvokeOfBase<IsInvokable<F, A...>, F, A...>::Type;
|
2015-04-23 19:38:18 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
template<typename F>
|
|
|
|
struct ResultOfBase {};
|
2015-04-24 18:43:20 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
template<typename F, typename ...A>
|
|
|
|
struct ResultOfBase<F(A...)> {
|
|
|
|
using Type = InvokeOf<F, A...>;
|
|
|
|
};
|
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
template<typename F>
|
|
|
|
using ResultOf = typename detail::ResultOfBase<F>::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:
|
2016-07-31 19:40:25 +00:00
|
|
|
using Type = Conditional<
|
|
|
|
IsArray<U>,
|
2015-07-05 22:59:36 +00:00
|
|
|
RemoveExtent<U> *,
|
2016-01-12 21:45:26 +00:00
|
|
|
Conditional<IsFunction<U>, 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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename ...T>
|
|
|
|
struct CommonTypeBase;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-07-31 19:40:25 +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
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00: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 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
|
|
|
|
2016-03-27 20:06:00 +00:00
|
|
|
template<typename ...A>
|
|
|
|
using CommonType = typename detail::CommonTypeBase<A...>::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 {
|
2016-07-31 19:40:25 +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
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +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)
|
2016-07-31 19:40:25 +00:00
|
|
|
>
|
|
|
|
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 {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<Size ...N>
|
|
|
|
constexpr Size AlignMax = 0;
|
|
|
|
template<Size N>
|
|
|
|
constexpr Size AlignMax<N> = N;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<Size N1, Size N2>
|
|
|
|
constexpr Size AlignMax<N1, N2> = (N1 > N2) ? N1 : N2;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<Size N1, Size N2, Size ...N>
|
2016-01-14 21:16:42 +00:00
|
|
|
constexpr Size AlignMax<N1, N2, N...> = AlignMax<AlignMax<N1, N2>, N...>;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<Size N, typename ...T>
|
|
|
|
struct AlignedUnionBase {
|
|
|
|
static constexpr Size alignment_value = AlignMax<alignof(T)...>;
|
2015-04-23 17:47:33 +00:00
|
|
|
|
2016-09-06 17:55:17 +00:00
|
|
|
struct Type {
|
2016-01-14 21:16:42 +00:00
|
|
|
alignas(alignment_value) byte data[AlignMax<N, sizeof(T)...>];
|
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... */
|
2016-07-31 19:40:25 +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
|
|
|
|
2016-02-07 21:17:15 +00:00
|
|
|
#endif
|