• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef API_BASE_CONTAINERS_TYPE_TRAITS_H
17 #define API_BASE_CONTAINERS_TYPE_TRAITS_H
18 
19 #include <cstddef>
20 
21 #include <base/namespace.h>
22 
23 BASE_BEGIN_NAMESPACE()
24 template<class T, T v>
25 struct integral_constant {
26     static constexpr T value = v;
27     using value_type = T;
28     using type = integral_constant;
value_typeintegral_constant29     constexpr operator value_type() const noexcept
30     {
31         return (value);
32     }
operatorintegral_constant33     constexpr value_type operator()() const noexcept
34     {
35         return (value);
36     }
37 };
38 
39 using false_type = integral_constant<bool, false>;
40 using true_type = integral_constant<bool, true>;
41 
42 template<bool B, class T = void>
43 struct enable_if {};
44 template<class T>
45 struct enable_if<true, T> {
46     using type = T;
47 };
48 template<bool B, class T = void>
49 using enable_if_t = typename enable_if<B, T>::type;
50 
51 template<class T, class U>
52 struct is_same : false_type {};
53 template<class T>
54 struct is_same<T, T> : true_type {};
55 
56 template<class T, class U>
57 constexpr auto is_same_v = is_same<T, U>::value;
58 
59 template<class T>
60 struct remove_extent {
61     using type = T;
62 };
63 template<class T>
64 struct remove_extent<T[]> {
65     using type = T;
66 };
67 template<class T, size_t N>
68 struct remove_extent<T[N]> {
69     using type = T;
70 };
71 template<class T>
72 using remove_extent_t = typename remove_extent<T>::type;
73 
74 template<class T, unsigned N = 0>
75 struct extent : integral_constant<size_t, 0> {};
76 
77 template<class T>
78 struct extent<T[], 0> : integral_constant<size_t, 0> {};
79 
80 template<class T, unsigned N>
81 struct extent<T[], N> : extent<T, N - 1> {};
82 
83 template<class T, size_t I>
84 struct extent<T[I], 0> : integral_constant<size_t, I> {};
85 
86 template<class T, size_t I, unsigned N>
87 struct extent<T[I], N> : extent<T, N - 1> {};
88 
89 template<class T, unsigned N = 0>
90 inline constexpr size_t extent_v = extent<T, N>::value;
91 
92 template<class T>
93 struct remove_const {
94     using type = T;
95 };
96 template<class T>
97 struct remove_const<const T> {
98     using type = T;
99 };
100 template<class T>
101 using remove_const_t = typename remove_const<T>::type;
102 
103 template<class T>
104 struct is_const : false_type {};
105 template<class T>
106 struct is_const<const T> : true_type {};
107 template<class T>
108 constexpr auto is_const_v = is_const<T>::value;
109 
110 template<class T>
111 struct is_array : false_type {};
112 template<class T>
113 struct is_array<T[]> : true_type {};
114 template<class T, size_t N>
115 struct is_array<T[N]> : true_type {};
116 template<class T>
117 constexpr bool is_array_v = is_array<T>::value;
118 template<class T>
119 using is_array_t = typename is_array<T>::type;
120 
121 template<class T>
122 struct is_pointer : false_type {};
123 template<class T>
124 struct is_pointer<T*> : true_type {};
125 template<class T>
126 constexpr auto is_pointer_v = is_pointer<T>::value;
127 
128 template<class T>
129 struct is_reference : false_type {};
130 template<class T>
131 struct is_reference<T&> : true_type {};
132 template<class T>
133 struct is_reference<T&&> : true_type {};
134 template<class T>
135 constexpr bool is_reference_v = is_reference<T>::value;
136 
137 template<class T>
138 struct is_lvalue_reference : false_type {};
139 template<class T>
140 struct is_lvalue_reference<T&> : true_type {};
141 template<class T>
142 constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value;
143 
144 template<class T>
145 struct is_rvalue_reference : false_type {};
146 template<class T>
147 struct is_rvalue_reference<T&&> : true_type {};
148 template<class T>
149 constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value;
150 
151 template<class... _Types>
152 using void_t = void;
153 
154 template<class T, class = void>
155 struct add_lvalue_reference {
156     using type = T;
157 };
158 template<class T, class = void>
159 struct add_rvalue_reference {
160     using type = T;
161 };
162 template<class T>
163 struct add_lvalue_reference<T, void_t<T&>> {
164     using type = T&;
165 };
166 template<class T>
167 struct add_rvalue_reference<T, void_t<T&>> {
168     using type = T&&;
169 };
170 template<class T>
171 using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
172 template<class T>
173 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
174 
175 template<class T>
176 struct remove_pointer {
177     using type = T;
178 };
179 template<class T>
180 struct remove_pointer<T*> {
181     using type = T;
182 };
183 template<class T>
184 struct remove_pointer<T* const> {
185     using type = T;
186 };
187 template<class T>
188 using remove_pointer_t = typename remove_pointer<T>::type;
189 
190 template<class T>
191 add_rvalue_reference_t<T> declval() noexcept;
192 
193 template<class T>
194 struct remove_reference {
195     using type = T;
196 };
197 
198 template<class T>
199 struct remove_reference<T&> {
200     using type = T;
201 };
202 
203 template<class T>
204 struct remove_reference<T&&> {
205     using type = T;
206 };
207 
208 template<class T>
209 using remove_reference_t = typename remove_reference<T>::type;
210 
211 template<class T>
212 constexpr remove_reference_t<T>&& move(T&& obj) noexcept
213 {
214     static_assert(!is_const<typename remove_reference<T>::type>::value, "move of const object is invalid.");
215     return (static_cast<remove_reference_t<T>&&>(obj));
216 }
217 
218 template<class T>
219 constexpr T&& forward(remove_reference_t<T>& obj) noexcept
220 {
221     return (static_cast<T&&>(obj));
222 }
223 
224 template<class T>
225 constexpr T&& forward(remove_reference_t<T>&& obj) noexcept
226 {
227     static_assert(!is_lvalue_reference_v<T>, "bad forward call");
228     return (static_cast<T&&>(obj));
229 }
230 
231 using nullptr_t = decltype(nullptr);
232 
233 template<class T, class U = T>
234 constexpr T exchange(T& obj, U&& newValue)
235 {
236     T old_value = move(obj);
237     obj = forward<U>(newValue);
238     return old_value;
239 }
240 
241 template<typename T>
242 struct type_identity {
243     using type = T;
244 };
245 
246 template<class T>
247 using type_identity_t = typename type_identity<T>::type;
248 
249 template<bool Condition, class TrueType, class FalseType>
250 struct conditional {
251     using type = TrueType;
252 };
253 template<class TrueType, class FalseType>
254 struct conditional<false, TrueType, FalseType> {
255     using type = FalseType;
256 };
257 template<bool Condition, class TrueType, class FalseType>
258 using conditional_t = typename conditional<Condition, TrueType, FalseType>::type;
259 
260 template<class T>
261 struct is_void : is_same<void, remove_const_t<T>> {};
262 template<typename T>
263 inline constexpr bool is_void_v = is_void<T>::value;
264 
265 template<typename T>
266 struct is_floating_point
267     : integral_constant<bool, is_same_v<float, remove_const_t<T>> || is_same_v<double, remove_const_t<T>> ||
268                                   is_same_v<long double, remove_const_t<T>>> {};
269 template<typename T>
270 inline constexpr bool is_floating_point_v = is_floating_point<T>::value;
271 
272 namespace detail {
273 template<typename T>
274 struct is_integral : false_type {};
275 
276 template<>
277 struct is_integral<bool> : true_type {};
278 
279 template<>
280 struct is_integral<signed char> : true_type {};
281 
282 template<>
283 struct is_integral<short> : true_type {};
284 
285 template<>
286 struct is_integral<int> : true_type {};
287 
288 template<>
289 struct is_integral<long> : true_type {};
290 
291 template<>
292 struct is_integral<long long> : true_type {};
293 
294 template<>
295 struct is_integral<unsigned char> : true_type {};
296 
297 template<>
298 struct is_integral<unsigned short> : true_type {};
299 
300 template<>
301 struct is_integral<unsigned int> : true_type {};
302 
303 template<>
304 struct is_integral<unsigned long> : true_type {};
305 
306 template<>
307 struct is_integral<unsigned long long> : true_type {};
308 } // namespace detail
309 
310 template<typename T>
311 struct is_integral : detail::is_integral<remove_const_t<T>>::type {};
312 
313 template<class T>
314 inline constexpr bool is_integral_v = is_integral<T>::value;
315 
316 template<class T>
317 struct is_arithmetic : integral_constant<bool, is_integral_v<T> || is_floating_point_v<T>> {};
318 
319 template<class T>
320 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
321 
322 template<typename T, bool = is_arithmetic_v<T>>
323 struct is_unsigned : integral_constant<bool, T(0) < T(-1)> {};
324 
325 template<typename T>
326 struct is_unsigned<T, false> : false_type {};
327 
328 template<typename T>
329 inline constexpr bool is_unsigned_v = is_unsigned<T>::value;
330 
331 template<typename T, bool = is_arithmetic_v<T>>
332 struct is_signed : integral_constant<bool, T(-1) < T(0)> {};
333 
334 template<typename T>
335 struct is_signed<T, false> : false_type {};
336 
337 template<typename T>
338 inline constexpr bool is_signed_v = is_signed<T>::value;
339 
340 namespace detail {
341 template<typename T>
342 auto is_returnable(int) -> decltype(void(static_cast<T (*)()>(nullptr)), true_type {});
343 
344 template<typename>
345 auto is_returnable(...) -> false_type;
346 
347 template<typename T>
348 inline constexpr bool is_returnable_v = decltype(is_returnable<T>(0))::value;
349 
350 template<typename From, typename To>
351 auto is_implicitly_convertible(int) -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type {});
352 
353 template<typename, typename>
354 auto is_implicitly_convertible(...) -> false_type;
355 
356 template<typename From, typename To>
357 inline constexpr bool is_implicitly_convertible_v = decltype(is_implicitly_convertible<From, To>(0))::value;
358 } // namespace detail
359 
360 template<typename From, typename To>
361 struct is_convertible
362     : integral_constant<bool, (is_void_v<From> && is_void_v<To>) ||
363                                   (detail::is_returnable_v<To> && detail::is_implicitly_convertible_v<From, To>)> {};
364 template<typename From, typename To>
365 constexpr bool is_convertible_v = is_convertible<From, To>::value;
366 
367 // return underlying type, works atleast for enums.
368 template<typename _Ty>
369 struct underlying_type {
370     using type = __underlying_type(_Ty);
371 };
372 template<typename _Ty>
373 using underlying_type_t = typename underlying_type<_Ty>::type;
374 
375 template<typename T, size_t N>
376 constexpr size_t countof(T (&)[N]) noexcept
377 {
378     return N;
379 }
380 BASE_END_NAMESPACE()
381 
382 #endif // API_BASE_TYPE_TRAITS_H
383