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