• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 Base, class Derived>
60 struct is_base_of : integral_constant<bool, __is_base_of(Base, Derived)> {};
61 
62 template<class Base, class Derived>
63 constexpr bool is_base_of_v = is_base_of<Base, Derived>::value;
64 
65 template<class T>
66 struct remove_extent {
67     using type = T;
68 };
69 template<class T>
70 struct remove_extent<T[]> {
71     using type = T;
72 };
73 template<class T, size_t N>
74 struct remove_extent<T[N]> {
75     using type = T;
76 };
77 template<class T>
78 using remove_extent_t = typename remove_extent<T>::type;
79 
80 template<class T, unsigned N = 0>
81 struct extent : integral_constant<size_t, 0> {};
82 
83 template<class T>
84 struct extent<T[], 0> : integral_constant<size_t, 0> {};
85 
86 template<class T, unsigned N>
87 struct extent<T[], N> : extent<T, N - 1> {};
88 
89 template<class T, size_t I>
90 struct extent<T[I], 0> : integral_constant<size_t, I> {};
91 
92 template<class T, size_t I, unsigned N>
93 struct extent<T[I], N> : extent<T, N - 1> {};
94 
95 template<class T, unsigned N = 0>
96 inline constexpr size_t extent_v = extent<T, N>::value;
97 
98 template<class T>
99 struct remove_const {
100     using type = T;
101 };
102 template<class T>
103 struct remove_const<const T> {
104     using type = T;
105 };
106 template<class T>
107 using remove_const_t = typename remove_const<T>::type;
108 
109 template<class T>
110 struct is_const : false_type {};
111 template<class T>
112 struct is_const<const T> : true_type {};
113 template<class T>
114 constexpr auto is_const_v = is_const<T>::value;
115 
116 template<class T>
117 struct is_array : false_type {};
118 template<class T>
119 struct is_array<T[]> : true_type {};
120 template<class T, size_t N>
121 struct is_array<T[N]> : true_type {};
122 template<class T>
123 constexpr bool is_array_v = is_array<T>::value;
124 template<class T>
125 using is_array_t = typename is_array<T>::type;
126 
127 template<class T>
128 struct is_pointer : false_type {};
129 template<class T>
130 struct is_pointer<T*> : true_type {};
131 template<class T>
132 constexpr auto is_pointer_v = is_pointer<T>::value;
133 
134 template<class T>
135 struct is_reference : false_type {};
136 template<class T>
137 struct is_reference<T&> : true_type {};
138 template<class T>
139 struct is_reference<T&&> : true_type {};
140 template<class T>
141 constexpr bool is_reference_v = is_reference<T>::value;
142 
143 template<class T>
144 struct is_lvalue_reference : false_type {};
145 template<class T>
146 struct is_lvalue_reference<T&> : true_type {};
147 template<class T>
148 constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value;
149 
150 template<class T>
151 struct is_rvalue_reference : false_type {};
152 template<class T>
153 struct is_rvalue_reference<T&&> : true_type {};
154 template<class T>
155 constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value;
156 
157 template<class... _Types>
158 using void_t = void;
159 
160 template<class T, class = void>
161 struct add_lvalue_reference {
162     using type = T;
163 };
164 template<class T, class = void>
165 struct add_rvalue_reference {
166     using type = T;
167 };
168 template<class T>
169 struct add_lvalue_reference<T, void_t<T&>> {
170     using type = T&;
171 };
172 template<class T>
173 struct add_rvalue_reference<T, void_t<T&>> {
174     using type = T&&;
175 };
176 template<class T>
177 using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
178 template<class T>
179 using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
180 
181 template<class T>
182 struct remove_pointer {
183     using type = T;
184 };
185 template<class T>
186 struct remove_pointer<T*> {
187     using type = T;
188 };
189 template<class T>
190 struct remove_pointer<T* const> {
191     using type = T;
192 };
193 template<class T>
194 using remove_pointer_t = typename remove_pointer<T>::type;
195 
196 template<class T>
197 add_rvalue_reference_t<T> declval() noexcept;
198 
199 template<class T>
200 struct remove_reference {
201     using type = T;
202 };
203 
204 template<class T>
205 struct remove_reference<T&> {
206     using type = T;
207 };
208 
209 template<class T>
210 struct remove_reference<T&&> {
211     using type = T;
212 };
213 
214 template<class T>
215 using remove_reference_t = typename remove_reference<T>::type;
216 
217 template<class T>
218 constexpr remove_reference_t<T>&& move(T&& obj) noexcept
219 {
220     static_assert(!is_const<typename remove_reference<T>::type>::value, "move of const object is invalid.");
221     return (static_cast<remove_reference_t<T>&&>(obj));
222 }
223 
224 template<class T>
225 constexpr T&& forward(remove_reference_t<T>& obj) noexcept
226 {
227     return (static_cast<T&&>(obj));
228 }
229 
230 template<class T>
231 constexpr T&& forward(remove_reference_t<T>&& obj) noexcept
232 {
233     static_assert(!is_lvalue_reference_v<T>, "bad forward call");
234     return (static_cast<T&&>(obj));
235 }
236 
237 using nullptr_t = decltype(nullptr);
238 
239 template<class T, class U = T>
240 constexpr T exchange(T& obj, U&& newValue)
241 {
242     T old_value = move(obj);
243     obj = forward<U>(newValue);
244     return old_value;
245 }
246 
247 template<typename T>
248 struct type_identity {
249     using type = T;
250 };
251 
252 template<class T>
253 using type_identity_t = typename type_identity<T>::type;
254 
255 template<bool Condition, class TrueType, class FalseType>
256 struct conditional {
257     using type = TrueType;
258 };
259 template<class TrueType, class FalseType>
260 struct conditional<false, TrueType, FalseType> {
261     using type = FalseType;
262 };
263 template<bool Condition, class TrueType, class FalseType>
264 using conditional_t = typename conditional<Condition, TrueType, FalseType>::type;
265 
266 template<class T>
267 struct is_void : is_same<void, remove_const_t<T>> {};
268 template<typename T>
269 inline constexpr bool is_void_v = is_void<T>::value;
270 
271 template<typename T>
272 struct is_floating_point
273     : integral_constant<bool, is_same_v<float, remove_const_t<T>> || is_same_v<double, remove_const_t<T>> ||
274                                   is_same_v<long double, remove_const_t<T>>> {};
275 template<typename T>
276 inline constexpr bool is_floating_point_v = is_floating_point<T>::value;
277 
278 namespace detail {
279 template<typename T>
280 struct is_integral : false_type {};
281 
282 template<>
283 struct is_integral<bool> : true_type {};
284 
285 template<>
286 struct is_integral<signed char> : true_type {};
287 
288 template<>
289 struct is_integral<short> : true_type {};
290 
291 template<>
292 struct is_integral<int> : true_type {};
293 
294 template<>
295 struct is_integral<long> : true_type {};
296 
297 template<>
298 struct is_integral<long long> : true_type {};
299 
300 template<>
301 struct is_integral<unsigned char> : true_type {};
302 
303 template<>
304 struct is_integral<unsigned short> : true_type {};
305 
306 template<>
307 struct is_integral<unsigned int> : true_type {};
308 
309 template<>
310 struct is_integral<unsigned long> : true_type {};
311 
312 template<>
313 struct is_integral<unsigned long long> : true_type {};
314 } // namespace detail
315 
316 template<typename T>
317 struct is_integral : detail::is_integral<remove_const_t<T>>::type {};
318 
319 template<class T>
320 inline constexpr bool is_integral_v = is_integral<T>::value;
321 
322 template<class T>
323 struct is_arithmetic : integral_constant<bool, is_integral_v<T> || is_floating_point_v<T>> {};
324 
325 template<class T>
326 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
327 
328 template<typename T, bool = is_arithmetic_v<T>>
329 struct is_unsigned : integral_constant<bool, T(0) < T(-1)> {};
330 
331 template<typename T>
332 struct is_unsigned<T, false> : false_type {};
333 
334 template<typename T>
335 inline constexpr bool is_unsigned_v = is_unsigned<T>::value;
336 
337 template<typename T, bool = is_arithmetic_v<T>>
338 struct is_signed : integral_constant<bool, T(-1) < T(0)> {};
339 
340 template<typename T>
341 struct is_signed<T, false> : false_type {};
342 
343 template<typename T>
344 inline constexpr bool is_signed_v = is_signed<T>::value;
345 
346 template<class T, class... Args>
347 struct is_constructible : integral_constant<bool, __is_constructible(T, Args...)> {};
348 
349 template<class T, class... Args>
350 constexpr bool is_constructible_v = is_constructible<T, Args...>::value;
351 
352 template<class T, class... Args>
353 struct is_trivially_constructible : integral_constant<bool, __is_trivially_constructible(T, Args...)> {};
354 
355 template<class T, class... Args>
356 constexpr bool is_trivially_constructible_v = is_trivially_constructible<T, Args...>::value;
357 
358 template<class T, class... Args>
359 struct is_nothrow_constructible : integral_constant<bool, __is_nothrow_constructible(T, Args...)> {};
360 
361 template<class T, class... Args>
362 constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<T, Args...>::value;
363 
364 template<class T>
365 struct is_default_constructible : is_constructible<T> {};
366 
367 template<class T>
368 inline constexpr bool is_default_constructible_v = is_default_constructible<T>::value;
369 
370 template<class T>
371 struct is_trivially_default_constructible : is_trivially_constructible<T> {};
372 
373 template<class T>
374 inline constexpr bool is_trivially_default_constructible_v = is_trivially_default_constructible<T>::value;
375 
376 template<class T>
377 struct is_nothrow_default_constructible : is_nothrow_constructible<T> {};
378 
379 template<class T>
380 inline constexpr bool is_nothrow_default_constructible_v = is_nothrow_default_constructible<T>::value;
381 
382 template<class T>
383 struct is_copy_constructible : is_constructible<T, add_lvalue_reference_t<const T>> {};
384 
385 template<class T>
386 inline constexpr bool is_copy_constructible_v = is_copy_constructible<T>::value;
387 
388 template<class T>
389 struct is_nothrow_copy_constructible : is_nothrow_constructible<T, add_lvalue_reference_t<const T>> {};
390 
391 template<class T>
392 constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<T>::value;
393 
394 template<class To, class From>
395 struct is_assignable : integral_constant<bool, __is_assignable(To, From)> {};
396 
397 template<class To, class From>
398 constexpr bool is_assignable_v = is_assignable<To, From>::value;
399 
400 template<class To, class From>
401 struct is_trivially_assignable : integral_constant<bool, __is_trivially_assignable(To, From)> {};
402 
403 template<class To, class From>
404 constexpr bool is_trivially_assignable_v = is_trivially_assignable<To, From>::value;
405 
406 template<class To, class From>
407 struct is_nothrow_assignable : integral_constant<bool, __is_nothrow_assignable(To, From)> {};
408 
409 template<class To, class From>
410 constexpr bool is_nothrow_assignable_v = is_nothrow_assignable<To, From>::value;
411 
412 template<class T>
413 struct is_copy_assignable : is_assignable<add_lvalue_reference_t<T>, add_lvalue_reference_t<const T>> {};
414 
415 template<class T>
416 constexpr bool is_copy_assignable_v = is_copy_assignable<T>::value;
417 
418 template<class T>
419 struct is_trivially_copy_assignable
420     : is_trivially_assignable<add_lvalue_reference_t<T>, add_lvalue_reference_t<const T>> {};
421 
422 template<class T>
423 constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<T>::value;
424 
425 template<class T>
426 struct is_nothrow_copy_assignable : is_nothrow_assignable<add_lvalue_reference_t<T>, add_lvalue_reference_t<const T>> {
427 };
428 
429 template<class T>
430 constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<T>::value;
431 
432 template<class T>
433 struct is_move_assignable : is_assignable<add_lvalue_reference_t<T>, T> {};
434 
435 template<class T>
436 constexpr bool is_move_assignable_v = is_move_assignable<T>::value;
437 
438 template<class T>
439 struct is_trivially_move_assignable : is_trivially_assignable<add_lvalue_reference_t<T>, T> {};
440 
441 template<class T>
442 constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<T>::value;
443 
444 template<class T>
445 struct is_nothrow_move_assignable : is_nothrow_assignable<add_lvalue_reference_t<T>, T> {};
446 
447 template<class T>
448 constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<T>::value;
449 
450 namespace detail {
451 template<typename T>
452 auto is_returnable(int) -> decltype(void(static_cast<T (*)()>(nullptr)), true_type {});
453 
454 template<typename>
455 auto is_returnable(...) -> false_type;
456 
457 template<typename T>
458 inline constexpr bool is_returnable_v = decltype(is_returnable<T>(0))::value;
459 
460 template<typename From, typename To>
461 auto is_implicitly_convertible(int) -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type {});
462 
463 template<typename, typename>
464 auto is_implicitly_convertible(...) -> false_type;
465 
466 template<typename From, typename To>
467 inline constexpr bool is_implicitly_convertible_v = decltype(is_implicitly_convertible<From, To>(0))::value;
468 } // namespace detail
469 
470 template<typename From, typename To>
471 struct is_convertible
472     : integral_constant<bool, (is_void_v<From> && is_void_v<To>) ||
473                                   (detail::is_returnable_v<To> && detail::is_implicitly_convertible_v<From, To>)> {};
474 template<typename From, typename To>
475 constexpr bool is_convertible_v = is_convertible<From, To>::value;
476 
477 // return underlying type, works atleast for enums.
478 template<typename _Ty>
479 struct underlying_type {
480     using type = __underlying_type(_Ty);
481 };
482 template<typename _Ty>
483 using underlying_type_t = typename underlying_type<_Ty>::type;
484 
485 template<typename T, size_t N>
486 constexpr size_t countof(T (&)[N]) noexcept
487 {
488     return N;
489 }
490 BASE_END_NAMESPACE()
491 
492 #endif // API_BASE_TYPE_TRAITS_H
493