1 //===-- Self contained C++ type traits --------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H 10 #define LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H 11 12 #include "UInt.h" 13 14 namespace __llvm_libc { 15 namespace cpp { 16 17 template <bool B, typename T> struct EnableIf; 18 template <typename T> struct EnableIf<true, T> { 19 typedef T Type; 20 }; 21 22 template <bool B, typename T> 23 using EnableIfType = typename EnableIf<B, T>::Type; 24 25 struct TrueValue { 26 static constexpr bool Value = true; 27 }; 28 29 struct FalseValue { 30 static constexpr bool Value = false; 31 }; 32 33 template <typename T> struct TypeIdentity { 34 typedef T Type; 35 }; 36 37 template <typename T1, typename T2> struct IsSame : public FalseValue {}; 38 template <typename T> struct IsSame<T, T> : public TrueValue {}; 39 template <typename T1, typename T2> 40 static constexpr bool IsSameV = IsSame<T1, T2>::Value; 41 42 template <typename T> struct RemoveCV : public TypeIdentity<T> {}; 43 template <typename T> struct RemoveCV<const T> : public TypeIdentity<T> {}; 44 template <typename T> struct RemoveCV<volatile T> : public TypeIdentity<T> {}; 45 template <typename T> 46 struct RemoveCV<const volatile T> : public TypeIdentity<T> {}; 47 48 template <typename T> using RemoveCVType = typename RemoveCV<T>::Type; 49 50 template <typename Type> struct IsIntegral { 51 using TypeNoCV = RemoveCVType<Type>; 52 static constexpr bool Value = 53 IsSameV<char, TypeNoCV> || IsSameV<signed char, TypeNoCV> || 54 IsSameV<unsigned char, TypeNoCV> || IsSameV<short, TypeNoCV> || 55 IsSameV<unsigned short, TypeNoCV> || IsSameV<int, TypeNoCV> || 56 IsSameV<unsigned int, TypeNoCV> || IsSameV<long, TypeNoCV> || 57 IsSameV<unsigned long, TypeNoCV> || IsSameV<long long, TypeNoCV> || 58 IsSameV<unsigned long long, TypeNoCV> || IsSameV<bool, TypeNoCV> || 59 // We need to include UInt<128> and __uint128_t when available because 60 // we want to unittest UInt<128>. If we include only UInt128, then on 61 // platform where it resolves to __uint128_t, we cannot unittest 62 // UInt<128>. 63 IsSameV<__llvm_libc::cpp::UInt<128>, TypeNoCV> 64 #ifdef __SIZEOF_INT128__ 65 || IsSameV<__int128_t, TypeNoCV> || IsSameV<__uint128_t, TypeNoCV> 66 #endif 67 ; 68 }; 69 70 template <typename Type> struct IsEnum { 71 static constexpr bool Value = __is_enum(Type); 72 }; 73 74 template <typename T> struct IsPointerTypeNoCV : public FalseValue {}; 75 template <typename T> struct IsPointerTypeNoCV<T *> : public TrueValue {}; 76 template <typename T> struct IsPointerType { 77 static constexpr bool Value = IsPointerTypeNoCV<RemoveCVType<T>>::Value; 78 }; 79 80 template <typename Type> struct IsFloatingPointType { 81 using TypeNoCV = RemoveCVType<Type>; 82 static constexpr bool Value = IsSame<float, TypeNoCV>::Value || 83 IsSame<double, TypeNoCV>::Value || 84 IsSame<long double, TypeNoCV>::Value; 85 }; 86 87 template <typename Type> struct IsArithmetic { 88 static constexpr bool Value = 89 IsIntegral<Type>::Value || IsFloatingPointType<Type>::Value; 90 }; 91 92 template <typename Type> struct IsSigned { 93 static constexpr bool Value = 94 IsArithmetic<Type>::Value && (Type(-1) < Type(0)); 95 constexpr operator bool() const { return Value; } 96 constexpr bool operator()() const { return Value; } 97 }; 98 99 template <typename Type> struct MakeUnsigned; 100 template <> struct MakeUnsigned<char> { 101 using Type = unsigned char; 102 }; 103 template <> struct MakeUnsigned<signed char> { 104 using Type = unsigned char; 105 }; 106 template <> struct MakeUnsigned<short> { 107 using Type = unsigned short; 108 }; 109 template <> struct MakeUnsigned<int> { 110 using Type = unsigned int; 111 }; 112 template <> struct MakeUnsigned<long> { 113 using Type = unsigned long; 114 }; 115 template <> struct MakeUnsigned<long long> { 116 using Type = unsigned long long; 117 }; 118 template <> struct MakeUnsigned<unsigned char> { 119 using Type = unsigned char; 120 }; 121 template <> struct MakeUnsigned<unsigned short> { 122 using Type = unsigned short; 123 }; 124 template <> struct MakeUnsigned<unsigned int> { 125 using Type = unsigned int; 126 }; 127 template <> struct MakeUnsigned<unsigned long> { 128 using Type = unsigned long; 129 }; 130 template <> struct MakeUnsigned<unsigned long long> { 131 using Type = unsigned long long; 132 }; 133 #ifdef __SIZEOF_INT128__ 134 template <> struct MakeUnsigned<__int128_t> { 135 using Type = __uint128_t; 136 }; 137 template <> struct MakeUnsigned<__uint128_t> { 138 using Type = __uint128_t; 139 }; 140 #endif 141 142 template <typename T> using MakeUnsignedType = typename MakeUnsigned<T>::Type; 143 144 // Compile time type selection. 145 template <bool _, class TrueT, class FalseT> struct Conditional { 146 using type = TrueT; 147 }; 148 template <class TrueT, class FalseT> struct Conditional<false, TrueT, FalseT> { 149 using type = FalseT; 150 }; 151 template <bool Cond, typename TrueT, typename FalseT> 152 using ConditionalType = typename Conditional<Cond, TrueT, FalseT>::type; 153 154 } // namespace cpp 155 } // namespace __llvm_libc 156 157 #endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPETRAITS_H 158