HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
type_traits.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2019-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
8#pragma once
9
10#include "architecture.hpp"
11#include <cstdint>
12#include <type_traits>
13#include <string>
14#include <string_view>
15#include <memory>
16#include <variant>
17
18namespace hi::inline v1 {
19
20// clang-format off
21
29template<typename T> struct is_numeric_signed_integral : std::false_type {};
30template<> struct is_numeric_signed_integral<signed char> : std::true_type {};
31template<> struct is_numeric_signed_integral<signed short> : std::true_type {};
32template<> struct is_numeric_signed_integral<signed int> : std::true_type {};
33template<> struct is_numeric_signed_integral<signed long> : std::true_type {};
34template<> struct is_numeric_signed_integral<signed long long> : std::true_type {};
35
38template<typename T>
40
48template<typename T> struct is_numeric_unsigned_integral : std::false_type {};
49template<> struct is_numeric_unsigned_integral<unsigned int> : std::true_type {};
50template<> struct is_numeric_unsigned_integral<unsigned char> : std::true_type {};
51template<> struct is_numeric_unsigned_integral<unsigned short> : std::true_type {};
52template<> struct is_numeric_unsigned_integral<unsigned long> : std::true_type {};
53template<> struct is_numeric_unsigned_integral<unsigned long long> : std::true_type {};
54
57template<typename T>
59
68template<typename T> struct is_numeric_integral : std::false_type {};
69template<> struct is_numeric_integral<unsigned int> : std::true_type {};
70template<> struct is_numeric_integral<unsigned char> : std::true_type {};
71template<> struct is_numeric_integral<unsigned short> : std::true_type {};
72template<> struct is_numeric_integral<unsigned long> : std::true_type {};
73template<> struct is_numeric_integral<unsigned long long> : std::true_type {};
74template<> struct is_numeric_integral<signed char> : std::true_type {};
75template<> struct is_numeric_integral<signed short> : std::true_type {};
76template<> struct is_numeric_integral<signed int> : std::true_type {};
77template<> struct is_numeric_integral<signed long> : std::true_type {};
78template<> struct is_numeric_integral<signed long long> : std::true_type {};
79
82template<typename T> inline constexpr bool is_numeric_integral_v = is_numeric_integral<T>::value;
83
93template<typename T> struct is_numeric : std::false_type {};
94template<> struct is_numeric<unsigned char> : std::true_type {};
95template<> struct is_numeric<unsigned short> : std::true_type {};
96template<> struct is_numeric<unsigned int> : std::true_type {};
97template<> struct is_numeric<unsigned long> : std::true_type {};
98template<> struct is_numeric<unsigned long long> : std::true_type {};
99template<> struct is_numeric<signed char> : std::true_type {};
100template<> struct is_numeric<signed short> : std::true_type {};
101template<> struct is_numeric<signed int> : std::true_type {};
102template<> struct is_numeric<signed long> : std::true_type {};
103template<> struct is_numeric<signed long long> : std::true_type {};
104template<> struct is_numeric<float> : std::true_type {};
105template<> struct is_numeric<double> : std::true_type {};
106template<> struct is_numeric<long double> : std::true_type {};
107
110template<typename T> inline constexpr bool is_numeric_v = is_numeric<T>::value;
111
112template<typename T> struct is_character : std::false_type {};
113template<> struct is_character<char> : std::true_type {};
114template<> struct is_character<wchar_t> : std::true_type {};
115template<> struct is_character<char8_t> : std::true_type {};
116template<> struct is_character<char16_t> : std::true_type {};
117template<> struct is_character<char32_t> : std::true_type {};
118template<> struct is_character<char const> : std::true_type {};
119template<> struct is_character<wchar_t const> : std::true_type {};
120template<> struct is_character<char8_t const> : std::true_type {};
121template<> struct is_character<char16_t const> : std::true_type {};
122template<> struct is_character<char32_t const> : std::true_type {};
123
127template<typename T> inline constexpr bool is_character_v = is_character<T>::value;
128
133template<typename T> struct is_byte_like : std::false_type {};
134template<> struct is_byte_like<char> : std::true_type {};
135template<> struct is_byte_like<unsigned char> : std::true_type {};
136template<> struct is_byte_like<std::byte> : std::true_type {};
137template<> struct is_byte_like<char const> : std::true_type {};
138template<> struct is_byte_like<unsigned char const> : std::true_type {};
139template<> struct is_byte_like<std::byte const> : std::true_type {};
140
145template<typename T> inline constexpr bool is_byte_like_v = is_byte_like<T>::value;
146
149template<typename T> struct make_string { };
150template<> struct make_string<char> { using type = std::string; };
151template<> struct make_string<wchar_t> { using type = std::wstring; };
152template<> struct make_string<char8_t> { using type = std::u8string; };
153template<> struct make_string<char16_t> { using type = std::u16string; };
154template<> struct make_string<char32_t> { using type = std::u32string; };
155
158template<typename T> using make_string_t = typename make_string<T>::type;
159
162template<typename T> struct make_string_view { using type = void; };
163template<> struct make_string_view<char> { using type = std::string_view; };
164template<> struct make_string_view<wchar_t> { using type = std::wstring_view; };
165template<> struct make_string_view<char8_t> { using type = std::u8string_view; };
166template<> struct make_string_view<char16_t> { using type = std::u16string_view; };
167template<> struct make_string_view<char32_t> { using type = std::u32string_view; };
168
171template<typename T>
172using make_string_view_t = typename make_string_view<T>::type;
173
174template<typename T, typename U>
176 using type = decltype(static_cast<T>(0) + static_cast<U>(0));
177};
178
179template<typename T, typename U>
180using make_promote_t = typename make_promote<T,U>::type;
181
182template<typename T, typename Ei=void>
184 using type = uintmax_t;
185};
186
187template<std::unsigned_integral T>
188struct make_intmax<T> {
189 using type = uintmax_t;
190};
191
192template<std::signed_integral T>
193struct make_intmax<T> {
194 using type = intmax_t;
195};
196
197template<typename T>
198using make_intmax_t = typename make_intmax<T>::type;
199
203template<std::size_t N> struct has_native_intxx : std::false_type {};
204
208template<std::size_t N> struct has_native_uintxx : std::false_type {};
209
213template<std::size_t N> struct has_native_floatxx : std::false_type {};
214
218template<std::size_t N> struct has_intxx : has_native_intxx<N> {};
219
223template<std::size_t N> struct has_uintxx : has_native_uintxx<N> {};
224
225
229template<std::size_t N> struct has_floatxx : has_native_floatxx<N> {};
230
234template<std::size_t N> struct make_intxx {};
235
239template<std::size_t N> struct make_uintxx {};
240
244template<std::size_t N> struct make_floatxx {};
245
246#ifdef HI_HAS_INT128
247template<> struct has_native_intxx<128> : std::true_type {};
248template<> struct has_native_uintxx<128> : std::true_type {};
249#endif
250template<> struct has_native_intxx<64> : std::true_type {};
251template<> struct has_native_uintxx<64> : std::true_type {};
252template<> struct has_native_floatxx<64> : std::true_type {};
253template<> struct has_native_intxx<32> : std::true_type {};
254template<> struct has_native_uintxx<32> : std::true_type {};
255template<> struct has_native_floatxx<32> : std::true_type {};
256template<> struct has_native_intxx<16> : std::true_type {};
257template<> struct has_native_uintxx<16> : std::true_type {};
258template<> struct has_native_intxx<8> : std::true_type {};
259template<> struct has_native_uintxx<8> : std::true_type {};
260
261#ifdef HI_HAS_INT128
262template<> struct make_intxx<128> { using type = int128_t; };
263template<> struct make_uintxx<128> { using type = uint128_t; };
264#endif
265template<> struct make_intxx<64> { using type = int64_t; };
266template<> struct make_uintxx<64> { using type = uint64_t; };
267template<> struct make_floatxx<64> { using type = double; };
268template<> struct make_intxx<32> { using type = int32_t; };
269template<> struct make_uintxx<32> { using type = uint32_t; };
270template<> struct make_floatxx<32> { using type = float; };
271template<> struct make_intxx<16> { using type = int16_t; };
272template<> struct make_uintxx<16> { using type = uint16_t; };
273template<> struct make_intxx<8> { using type = int8_t; };
274template<> struct make_uintxx<8> { using type = uint8_t; };
275
276template<std::size_t N> constexpr bool has_native_intxx_v = has_native_intxx<N>::value;
277template<std::size_t N> constexpr bool has_native_uintxx_v = has_native_uintxx<N>::value;
278template<std::size_t N> constexpr bool has_native_floatxx_v = has_native_floatxx<N>::value;
279template<std::size_t N> constexpr bool has_intxx_v = has_intxx<N>::value;
280template<std::size_t N> constexpr bool has_uintxx_v = has_uintxx<N>::value;
281template<std::size_t N> constexpr bool has_floatxx_v = has_floatxx<N>::value;
282template<std::size_t N> using make_intxx_t = typename make_intxx<N>::type;
283template<std::size_t N> using make_uintxx_t = typename make_uintxx<N>::type;
284template<std::size_t N> using make_floatxx_t = typename make_floatxx<N>::type;
285
298template<typename L, typename... R>
300
301template<std::integral T>
302struct common_integer<T,T> {
303 using type = T;
304};
305
306template<std::unsigned_integral L, std::unsigned_integral R>
307struct common_integer<L,R> {
308 using type = std::conditional_t<(sizeof(L) > sizeof(R)), L, R>;
309};
310
311template<std::signed_integral L, std::signed_integral R>
312struct common_integer<L,R> {
313 using type = std::conditional_t<(sizeof(L) > sizeof(R)), L, R>;
314};
315
316template<std::unsigned_integral L, std::signed_integral R>
317struct common_integer<L,R> {
318 using _left_type =
319 std::conditional_t<(sizeof(L) < sizeof(short)), short,
320 std::conditional_t<(sizeof(L) < sizeof(int)), int,
321 std::conditional_t<(sizeof(L) < sizeof(long)), long, long long>>>;
322
323 using type = common_integer<_left_type, R>::type;
324};
325
326template<std::signed_integral L, std::unsigned_integral R>
327struct common_integer<L,R> {
328 using type = common_integer<R, L>::type;
329};
330
331template<std::integral L, std::integral M, std::integral... R>
332struct common_integer<L, M, R...> {
333 using type = common_integer<L, typename common_integer<M, R...>::type>::type;
334};
335
348template<std::integral L, std::integral... R>
349using common_integer_t = common_integer<L, R...>::type;
350
351template<typename T>
352struct remove_cvptr { using type = std::remove_cv_t<std::remove_pointer_t<T>>; };
353
354template<typename T>
355using remove_cvptr_t = remove_cvptr<T>::type;
356
359template<typename To, typename From, typename Ei=void>
360struct copy_cv {};
361
362template<typename To, typename From> requires(not std::is_const_v<From> and not std::is_volatile_v<From>)
364 using type = std::remove_cv_t<To>;
365};
366
367template<typename To, typename From> requires(not std::is_const_v<From> and std::is_volatile_v<From>)
368struct copy_cv<To,From> {
369 using type = std::remove_cv_t<To> volatile;
370};
371
372template<typename To, typename From> requires(std::is_const_v<From> and not std::is_volatile_v<From>)
373struct copy_cv<To,From> {
374 using type = std::remove_cv_t<To> const;
375};
376
377template<typename To, typename From> requires(std::is_const_v<From> and std::is_volatile_v<From>)
378struct copy_cv<To,From> {
379 using type = std::remove_cv_t<To> const volatile;
380};
381
384template<typename To, typename From>
386
387template <typename T> struct has_value_type
388{
389 template <typename C> static std::true_type test(typename C::value_type *);
390 template <typename> static std::false_type test(...);
391
392 static const bool value = std::is_same_v<decltype(test<T>(nullptr)), std::true_type>;
393};
394
395template<typename T>
396inline constexpr bool has_value_type_v = has_value_type<T>::value;
397
398template <typename T> struct has_add_callback
399{
400 template <typename C> static std::true_type test(decltype(&C::add_callback) func_ptr);
401 template <typename> static std::false_type test(...);
402
403 static const bool value = std::is_same_v<decltype(test<T>(nullptr)), std::true_type>;
404};
405
406template<typename T>
407inline constexpr bool has_add_callback_v = has_add_callback<T>::value;
408
409template<typename BaseType, typename DerivedType>
410struct is_decayed_base_of : std::is_base_of<std::decay_t<BaseType>,std::decay_t<DerivedType>> {};
411
412template<typename BaseType, typename DerivedType>
413constexpr bool is_decayed_base_of_v = is_decayed_base_of<BaseType,DerivedType>::value;
414
415template<typename DerivedType, typename BaseType>
416struct is_derived_from : std::is_base_of<BaseType,DerivedType> {};
417
418template<typename DerivedType, typename BaseType>
419constexpr bool is_derived_from_v = is_derived_from<DerivedType,BaseType>::value;
420
421template<typename DerivedType, typename BaseType>
422struct is_decayed_derived_from : is_decayed_base_of<BaseType,DerivedType> {};
423
424template<typename DerivedType, typename BaseType>
425constexpr bool is_decayed_derived_from_v = is_decayed_derived_from<DerivedType,BaseType>::value;
426
430template<typename Context, typename Expected>
431constexpr bool is_different_v = not std::is_same_v<std::decay_t<Context>,std::decay_t<Expected>>;
432
433template<typename T>
435
436template<typename T>
437struct is_atomic<std::atomic<T>> : std::true_type {};
438
439template<typename T>
440constexpr bool is_atomic_v = is_atomic<T>::value;
441
442template<typename First, typename Second>
443struct use_first {
444 using type = First;
445};
446
447template<typename First, typename Second>
449
455template<typename T>
459 constexpr static bool value = false;
460
463 using type = void;
464};
465
466template<typename T> struct smart_pointer_traits<std::shared_ptr<T>> {constexpr static bool value = true; using type = T;};
467template<typename T> struct smart_pointer_traits<std::weak_ptr<T>> {constexpr static bool value = true; using type = T;};
468template<typename T> struct smart_pointer_traits<std::unique_ptr<T>> {constexpr static bool value = true; using type = T;};
469template<typename T> struct smart_pointer_traits<T *> {constexpr static bool value = true; using type = T;};
470
478#define hi_call_method(object, method, ...) \
479 [&]() { \
480 if constexpr (smart_pointer_traits<std::decay_t<decltype(object)>>::value) { \
481 return object->method(__VA_ARGS__); \
482 } else { \
483 return object.method(__VA_ARGS__); \
484 } \
485 }()
486
489template<typename Out, typename In>
492
530template<typename Context, typename Expected, typename... OtherExpected>
532
533template<typename Context, typename Expected, typename FirstOtherExpected, typename... OtherExpected>
534struct is_forward_of<Context, Expected, FirstOtherExpected, OtherExpected...> : std::conditional_t<
535 is_forward_of<Context, Expected>::value or
536 (is_forward_of<Context, FirstOtherExpected>::value or ... or is_forward_of<Context, OtherExpected>::value),
537 std::true_type,
538 std::false_type> {};
539
540template<typename Context, typename Expected>
541struct is_forward_of<Context, Expected> :
542 std::conditional_t<
543 std::is_same_v<std::decay_t<Context>, Expected> or std::is_base_of_v<Expected, std::decay_t<Context>>,
544 std::true_type,
545 std::false_type> {
546 static_assert(not std::is_reference_v<Expected>, "Template argument Expected must be a non-reference type.");
547};
548
549template<typename Context, typename Expected>
550struct is_forward_of<Context, std::shared_ptr<Expected>> :
551 std::conditional_t<
552 std::is_convertible_v<Context, std::shared_ptr<Expected>>,
553 std::true_type,
554 std::false_type> {};
555
556template<typename Context, typename Expected>
557struct is_forward_of<Context, std::weak_ptr<Expected>> :
558 std::conditional_t<
559 std::is_convertible_v<Context, std::weak_ptr<Expected>>,
560 std::true_type,
561 std::false_type> {};
562
563template<typename Context, typename Expected>
564struct is_forward_of<Context, std::unique_ptr<Expected>> :
565 std::conditional_t<
566 std::is_convertible_v<Context, std::unique_ptr<Expected>>,
567 std::true_type,
568 std::false_type> {};
569
570template<typename Context, typename Expected>
571struct is_forward_of<Context, Expected *> :
572 std::conditional_t<
573 std::is_convertible_v<Context, Expected *>,
575 std::false_type> {};
576
577template<typename Context, typename Result, typename... Args>
578struct is_forward_of<Context, Result(Args...)> :
579 std::conditional_t<std::is_invocable_r_v<Result, Context, Args...>, std::true_type, std::false_type> {
580};
581
582template<typename Context, typename Expected, typename... OtherExpected>
583constexpr bool is_forward_of_v = is_forward_of<Context, Expected, OtherExpected...>::value;
584
585template<typename Context>
587 using type = std::conditional_t<std::is_rvalue_reference_v<Context>, std::decay_t<Context>, std::decay_t<Context> const &>;
588};
589
590template<typename Context>
591using forward_copy_or_ref_t = forward_copy_or_ref<Context>::type;
592
593
598template<typename T>
600 using type = std::decay_t<T>;
601};
602
603template<>
604struct variant_decay<void> {
605 using type = std::monostate;
606};
607
610template<typename T>
611using variant_decay_t = variant_decay<T>::type;
612
641template<typename T>
642struct selector;
643
644
661template<typename T>
663
664
665
670template<class... Ts>
671struct overloaded : Ts... {
672 // Makes the call operator of each lambda available directly to the `overloaded` type.
673 using Ts::operator()...;
674
675 // The implicit constructor is all that is needed to initialize each lambda.
676};
677
678} // namespace hi::inline v1
Functions and macros for handling architectural difference between compilers, CPUs and operating syst...
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:13
common_integer< L, R... >::type common_integer_t
Get an integer type that will fit all values from all template parameters.
Definition type_traits.hpp:349
constexpr bool is_numeric_v
Definition type_traits.hpp:110
constexpr bool is_different_v
If the types are different.
Definition type_traits.hpp:431
typename make_string< T >::type make_string_t
type-trait to convert a character to a string type.
Definition type_traits.hpp:158
typename make_string_view< T >::type make_string_view_t
type-trait to convert a character to a string_view type.
Definition type_traits.hpp:172
__int128 int128_t
Signed 128 bit integer.
Definition architecture.hpp:180
constexpr bool is_numeric_unsigned_integral_v
Definition type_traits.hpp:58
variant_decay< T >::type variant_decay_t
Definition type_traits.hpp:611
unsigned __int128 uint128_t
Unsigned 128 bit integer.
Definition architecture.hpp:184
constexpr bool is_byte_like_v
An array of this type will implicitly create objects within that array.
Definition type_traits.hpp:145
typename copy_cv< To, From >::type copy_cv_t
Type-trait to copy const volatile qualifiers from one type to another.
Definition type_traits.hpp:385
constexpr bool is_numeric_integral_v
Definition type_traits.hpp:82
constexpr bool type_in_range_v
All values of numeric type In can be represented without loss of range by numeric type Out.
Definition type_traits.hpp:490
constexpr bool is_character_v
Definition type_traits.hpp:127
constexpr bool is_numeric_signed_integral_v
Definition type_traits.hpp:39
Is a numeric signed integer.
Definition type_traits.hpp:29
Is a numeric unsigned integer.
Definition type_traits.hpp:48
Is a numeric integer.
Definition type_traits.hpp:68
Is a numeric.
Definition type_traits.hpp:93
Definition type_traits.hpp:112
An array of this type will implicitly create objects within that array.
Definition type_traits.hpp:133
type-trait to convert a character to a string type.
Definition type_traits.hpp:149
type-trait to convert a character to a string_view type.
Definition type_traits.hpp:162
Definition type_traits.hpp:175
Definition type_traits.hpp:183
Has an signed integer of a specific size, natively supported by the compiler.
Definition type_traits.hpp:203
Has an unsigned integer of a specific size, natively supported by the compiler.
Definition type_traits.hpp:208
Has an float of a specific size, natively supported by the compiler.
Definition type_traits.hpp:213
Has an signed integer of a specific size.
Definition type_traits.hpp:218
Has an unsigned integer of a specific size.
Definition type_traits.hpp:223
Has an float of a specific size.
Definition type_traits.hpp:229
Make an signed integer.
Definition type_traits.hpp:234
Make an unsigned integer.
Definition type_traits.hpp:239
Make an floating point.
Definition type_traits.hpp:244
Get an integer type that will fit all values from all template parameters.
Definition type_traits.hpp:299
Definition type_traits.hpp:352
Type-trait to copy const volatile qualifiers from one type to another.
Definition type_traits.hpp:360
Definition type_traits.hpp:388
Definition type_traits.hpp:399
Definition type_traits.hpp:410
Definition type_traits.hpp:416
Definition type_traits.hpp:422
Definition type_traits.hpp:434
Definition type_traits.hpp:443
Smart pointer traits.
Definition type_traits.hpp:456
void type
The type the pointer points to.
Definition type_traits.hpp:463
Is context a form of the expected type.
Definition type_traits.hpp:531
Definition type_traits.hpp:586
Decays types for use as elements in std::variant.
Definition type_traits.hpp:599
This selector allows access to member variable by name.
Definition type_traits.hpp:642
Documentation of a type.
Definition type_traits.hpp:662
Helper type to turn a set of lambdas into a single overloaded type to pass to std::visit().
Definition type_traits.hpp:671