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 "../macros.hpp"
11#include <cstdint>
12#include <type_traits>
13#include <string>
14#include <string_view>
15#include <memory>
16#include <variant>
17#include <atomic>
18
19hi_export_module(hikogui.utility.type_traits);
20
21hi_export namespace hi::inline v1 {
22
23// clang-format off
24
32template<typename T> struct is_numeric_signed_integral : std::false_type {};
38
41template<typename T>
43
51template<typename T> struct is_numeric_unsigned_integral : std::false_type {};
57
60template<typename T>
62
71template<typename T> struct is_numeric_integral : std::false_type {};
82
85template<typename T> inline constexpr bool is_numeric_integral_v = is_numeric_integral<T>::value;
86
96template<typename T> struct is_numeric : std::false_type {};
97template<> struct is_numeric<unsigned char> : std::true_type {};
98template<> struct is_numeric<unsigned short> : std::true_type {};
99template<> struct is_numeric<unsigned int> : std::true_type {};
100template<> struct is_numeric<unsigned long> : std::true_type {};
102template<> struct is_numeric<signed char> : std::true_type {};
103template<> struct is_numeric<signed short> : std::true_type {};
104template<> struct is_numeric<signed int> : std::true_type {};
105template<> struct is_numeric<signed long> : std::true_type {};
106template<> struct is_numeric<signed long long> : std::true_type {};
107template<> struct is_numeric<float> : std::true_type {};
108template<> struct is_numeric<double> : std::true_type {};
109template<> struct is_numeric<long double> : std::true_type {};
110
113template<typename T> inline constexpr bool is_numeric_v = is_numeric<T>::value;
114
115template<typename T> struct is_character : std::false_type {};
116template<> struct is_character<char> : std::true_type {};
117template<> struct is_character<wchar_t> : std::true_type {};
118template<> struct is_character<char8_t> : std::true_type {};
119template<> struct is_character<char16_t> : std::true_type {};
120template<> struct is_character<char32_t> : std::true_type {};
121template<> struct is_character<char const> : std::true_type {};
122template<> struct is_character<wchar_t const> : std::true_type {};
123template<> struct is_character<char8_t const> : std::true_type {};
126
130template<typename T> inline constexpr bool is_character_v = is_character<T>::value;
131
136template<typename T> struct is_byte_like : std::false_type {};
137template<> struct is_byte_like<char> : std::true_type {};
138template<> struct is_byte_like<unsigned char> : std::true_type {};
139template<> struct is_byte_like<std::byte> : std::true_type {};
140template<> struct is_byte_like<char const> : std::true_type {};
142template<> struct is_byte_like<std::byte const> : std::true_type {};
143
148template<typename T> inline constexpr bool is_byte_like_v = is_byte_like<T>::value;
149
152template<typename T> struct make_string { };
153template<> struct make_string<char> { using type = std::string; };
154template<> struct make_string<wchar_t> { using type = std::wstring; };
155template<> struct make_string<char8_t> { using type = std::u8string; };
156template<> struct make_string<char16_t> { using type = std::u16string; };
157template<> struct make_string<char32_t> { using type = std::u32string; };
158
161template<typename T> using make_string_t = typename make_string<T>::type;
162
165template<typename T> struct make_string_view { using type = void; };
166template<> struct make_string_view<char> { using type = std::string_view; };
167template<> struct make_string_view<wchar_t> { using type = std::wstring_view; };
168template<> struct make_string_view<char8_t> { using type = std::u8string_view; };
169template<> struct make_string_view<char16_t> { using type = std::u16string_view; };
170template<> struct make_string_view<char32_t> { using type = std::u32string_view; };
171
174template<typename T>
175using make_string_view_t = typename make_string_view<T>::type;
176
177template<typename T, typename U>
179 using type = decltype(static_cast<T>(0) + static_cast<U>(0));
180};
181
182template<typename T, typename U>
183using make_promote_t = typename make_promote<T,U>::type;
184
185template<typename T, typename Ei=void>
187 using type = uintmax_t;
188};
189
190template<std::unsigned_integral T>
191struct make_intmax<T> {
192 using type = uintmax_t;
193};
194
195template<std::signed_integral T>
196struct make_intmax<T> {
197 using type = intmax_t;
198};
199
200template<typename T>
201using make_intmax_t = typename make_intmax<T>::type;
202
206template<std::size_t N> struct has_native_intxx : std::false_type {};
207
211template<std::size_t N> struct has_native_uintxx : std::false_type {};
212
216template<std::size_t N> struct has_native_floatxx : std::false_type {};
217
221template<std::size_t N> struct has_intxx : has_native_intxx<N> {};
222
226template<std::size_t N> struct has_uintxx : has_native_uintxx<N> {};
227
228
232template<std::size_t N> struct has_floatxx : has_native_floatxx<N> {};
233
237template<std::size_t N> struct make_intxx {};
238
242template<std::size_t N> struct make_uintxx {};
243
247template<std::size_t N> struct make_floatxx {};
248
249#ifdef HI_HAS_INT128
250template<> struct has_native_intxx<128> : std::true_type {};
251template<> struct has_native_uintxx<128> : std::true_type {};
252#endif
253template<> struct has_native_intxx<64> : std::true_type {};
254template<> struct has_native_uintxx<64> : std::true_type {};
255template<> struct has_native_floatxx<64> : std::true_type {};
256template<> struct has_native_intxx<32> : std::true_type {};
257template<> struct has_native_uintxx<32> : std::true_type {};
258template<> struct has_native_floatxx<32> : std::true_type {};
259template<> struct has_native_intxx<16> : std::true_type {};
260template<> struct has_native_uintxx<16> : std::true_type {};
261template<> struct has_native_intxx<8> : std::true_type {};
262template<> struct has_native_uintxx<8> : std::true_type {};
263
264#ifdef HI_HAS_INT128
265template<> struct make_intxx<128> { using type = int128_t; };
266template<> struct make_uintxx<128> { using type = uint128_t; };
267#endif
268template<> struct make_intxx<64> { using type = int64_t; };
269template<> struct make_uintxx<64> { using type = uint64_t; };
270template<> struct make_floatxx<64> { using type = double; };
271template<> struct make_intxx<32> { using type = int32_t; };
272template<> struct make_uintxx<32> { using type = uint32_t; };
273template<> struct make_floatxx<32> { using type = float; };
274template<> struct make_intxx<16> { using type = int16_t; };
275template<> struct make_uintxx<16> { using type = uint16_t; };
276template<> struct make_intxx<8> { using type = int8_t; };
277template<> struct make_uintxx<8> { using type = uint8_t; };
278
279template<std::size_t N> constexpr bool has_native_intxx_v = has_native_intxx<N>::value;
280template<std::size_t N> constexpr bool has_native_uintxx_v = has_native_uintxx<N>::value;
281template<std::size_t N> constexpr bool has_native_floatxx_v = has_native_floatxx<N>::value;
282template<std::size_t N> constexpr bool has_intxx_v = has_intxx<N>::value;
283template<std::size_t N> constexpr bool has_uintxx_v = has_uintxx<N>::value;
284template<std::size_t N> constexpr bool has_floatxx_v = has_floatxx<N>::value;
285template<std::size_t N> using make_intxx_t = typename make_intxx<N>::type;
286template<std::size_t N> using make_uintxx_t = typename make_uintxx<N>::type;
287template<std::size_t N> using make_floatxx_t = typename make_floatxx<N>::type;
288
301template<typename L, typename... R>
303
304template<std::integral T>
305struct common_integer<T,T> {
306 using type = T;
307};
308
309template<std::unsigned_integral L, std::unsigned_integral R>
310struct common_integer<L,R> {
311 using type = std::conditional_t<(sizeof(L) > sizeof(R)), L, R>;
312};
313
314template<std::signed_integral L, std::signed_integral R>
315struct common_integer<L,R> {
316 using type = std::conditional_t<(sizeof(L) > sizeof(R)), L, R>;
317};
318
319template<std::unsigned_integral L, std::signed_integral R>
320struct common_integer<L,R> {
321 using _left_type =
322 std::conditional_t<(sizeof(L) < sizeof(short)), short,
323 std::conditional_t<(sizeof(L) < sizeof(int)), int,
324 std::conditional_t<(sizeof(L) < sizeof(long)), long, long long>>>;
325
326 using type = common_integer<_left_type, R>::type;
327};
328
329template<std::signed_integral L, std::unsigned_integral R>
330struct common_integer<L,R> {
331 using type = common_integer<R, L>::type;
332};
333
334template<std::integral L, std::integral M, std::integral... R>
335struct common_integer<L, M, R...> {
336 using type = common_integer<L, typename common_integer<M, R...>::type>::type;
337};
338
351template<std::integral L, std::integral... R>
352using common_integer_t = common_integer<L, R...>::type;
353
354template<typename T>
355struct remove_cvptr { using type = std::remove_cv_t<std::remove_pointer_t<T>>; };
356
357template<typename T>
358using remove_cvptr_t = remove_cvptr<T>::type;
359
362template<typename To, typename From, typename Ei=void>
363struct copy_cv {};
364
365template<typename To, typename From> requires(not std::is_const_v<From> and not std::is_volatile_v<From>)
367 using type = std::remove_cv_t<To>;
368};
369
370template<typename To, typename From> requires(not std::is_const_v<From> and std::is_volatile_v<From>)
371struct copy_cv<To,From> {
372 using type = std::remove_cv_t<To> volatile;
373};
374
375template<typename To, typename From> requires(std::is_const_v<From> and not std::is_volatile_v<From>)
376struct copy_cv<To,From> {
377 using type = std::remove_cv_t<To> const;
378};
379
380template<typename To, typename From> requires(std::is_const_v<From> and std::is_volatile_v<From>)
381struct copy_cv<To,From> {
382 using type = std::remove_cv_t<To> const volatile;
383};
384
387template<typename To, typename From>
389
390template <typename T> struct has_value_type
391{
392 template <typename C> static std::true_type test(typename C::value_type *);
393 template <typename> static std::false_type test(...);
394
395 static const bool value = std::is_same_v<decltype(test<T>(nullptr)), std::true_type>;
396};
397
398template<typename T>
399inline constexpr bool has_value_type_v = has_value_type<T>::value;
400
401template <typename T> struct has_add_callback
402{
403 template <typename C> static std::true_type test(decltype(&C::add_callback) func_ptr);
404 template <typename> static std::false_type test(...);
405
406 static const bool value = std::is_same_v<decltype(test<T>(nullptr)), std::true_type>;
407};
408
409template<typename T>
410inline constexpr bool has_add_callback_v = has_add_callback<T>::value;
411
412template<typename BaseType, typename DerivedType>
413struct is_decayed_base_of : std::is_base_of<std::decay_t<BaseType>,std::decay_t<DerivedType>> {};
414
415template<typename BaseType, typename DerivedType>
416constexpr bool is_decayed_base_of_v = is_decayed_base_of<BaseType,DerivedType>::value;
417
418template<typename DerivedType, typename BaseType>
419struct is_derived_from : std::is_base_of<BaseType,DerivedType> {};
420
421template<typename DerivedType, typename BaseType>
422constexpr bool is_derived_from_v = is_derived_from<DerivedType,BaseType>::value;
423
424template<typename DerivedType, typename BaseType>
425struct is_decayed_derived_from : is_decayed_base_of<BaseType,DerivedType> {};
426
427template<typename DerivedType, typename BaseType>
428constexpr bool is_decayed_derived_from_v = is_decayed_derived_from<DerivedType,BaseType>::value;
429
433template<typename Context, typename Expected>
434constexpr bool is_different_v = not std::is_same_v<std::decay_t<Context>,std::decay_t<Expected>>;
435
436template<typename T>
438
439template<typename T>
440struct is_atomic<std::atomic<T>> : std::true_type {};
441
442template<typename T>
443constexpr bool is_atomic_v = is_atomic<T>::value;
444
445template<typename First, typename Second>
446struct use_first {
447 using type = First;
448};
449
450template<typename First, typename Second>
452
458template<typename T>
462 constexpr static bool value = false;
463
466 using type = void;
467};
468
469template<typename T> struct smart_pointer_traits<std::shared_ptr<T>> {constexpr static bool value = true; using type = T;};
470template<typename T> struct smart_pointer_traits<std::weak_ptr<T>> {constexpr static bool value = true; using type = T;};
471template<typename T> struct smart_pointer_traits<std::unique_ptr<T>> {constexpr static bool value = true; using type = T;};
472template<typename T> struct smart_pointer_traits<T *> {constexpr static bool value = true; using type = T;};
473
481#define hi_call_method(object, method, ...) \
482 [&]() { \
483 if constexpr (smart_pointer_traits<std::decay_t<decltype(object)>>::value) { \
484 return object->method(__VA_ARGS__); \
485 } else { \
486 return object.method(__VA_ARGS__); \
487 } \
488 }()
489
492template<typename Out, typename In>
495
533template<typename Context, typename Expected, typename... OtherExpected>
535
536template<typename Context, typename Expected, typename FirstOtherExpected, typename... OtherExpected>
538 is_forward_of<Context, Expected>::value or
539 (is_forward_of<Context, FirstOtherExpected>::value or ... or is_forward_of<Context, OtherExpected>::value),
540 std::true_type,
541 std::false_type> {};
542
543template<typename Context, typename Expected>
545 std::conditional_t<
546 std::is_same_v<std::decay_t<Context>, Expected> or std::is_base_of_v<Expected, std::decay_t<Context>>,
547 std::true_type,
548 std::false_type> {
549 static_assert(not std::is_reference_v<Expected>, "Template argument Expected must be a non-reference type.");
550};
551
552template<typename Context, typename Expected>
553struct is_forward_of<Context, std::shared_ptr<Expected>> :
554 std::conditional_t<
555 std::is_convertible_v<Context, std::shared_ptr<Expected>>,
556 std::true_type,
557 std::false_type> {};
558
559template<typename Context, typename Expected>
560struct is_forward_of<Context, std::weak_ptr<Expected>> :
561 std::conditional_t<
562 std::is_convertible_v<Context, std::weak_ptr<Expected>>,
563 std::true_type,
564 std::false_type> {};
565
566template<typename Context, typename Expected>
567struct is_forward_of<Context, std::unique_ptr<Expected>> :
568 std::conditional_t<
569 std::is_convertible_v<Context, std::unique_ptr<Expected>>,
570 std::true_type,
571 std::false_type> {};
572
573template<typename Context, typename Expected>
575 std::conditional_t<
576 std::is_convertible_v<Context, Expected *>,
578 std::false_type> {};
579
580template<typename Context, typename Result, typename... Args>
582 std::conditional_t<std::is_invocable_r_v<Result, Context, Args...>, std::true_type, std::false_type> {
583};
584
585template<typename Context, typename Expected, typename... OtherExpected>
586constexpr bool is_forward_of_v = is_forward_of<Context, Expected, OtherExpected...>::value;
587
588template<typename Context>
590 using type = std::conditional_t<std::is_rvalue_reference_v<Context>, std::decay_t<Context>, std::decay_t<Context> const &>;
591};
592
593template<typename Context>
594using forward_copy_or_ref_t = forward_copy_or_ref<Context>::type;
595
596
601template<typename T>
603 using type = std::decay_t<T>;
604};
605
606template<>
608 using type = std::monostate;
609};
610
613template<typename T>
614using variant_decay_t = variant_decay<T>::type;
615
644template<typename T>
645struct selector;
646
647
664template<typename T>
666
667
668
673template<class... Ts>
674struct overloaded : Ts... {
675 // Makes the call operator of each lambda available directly to the `overloaded` type.
676 using Ts::operator()...;
677
678 // The implicit constructor is all that is needed to initialize each lambda.
679};
680
681
686template<typename T>
688
689template<std::integral T>
691{
692 constexpr static T off = T{};
693 constexpr static T on = T{1};
694};
695
696template<typename T> requires (std::is_enum_v<T>)
697struct default_values<T> : std::true_type {
698 constexpr static T off = static_cast<T>(0);
699 constexpr static T on = static_cast<T>(1);
700};
701
702template<typename T>
703constexpr bool default_values_v = default_values<T>::value;
704
705} // namespace hi::inline v1
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:16
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:352
constexpr bool is_numeric_v
Definition type_traits.hpp:113
constexpr bool is_different_v
If the types are different.
Definition type_traits.hpp:434
typename make_string< T >::type make_string_t
type-trait to convert a character to a string type.
Definition type_traits.hpp:161
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:175
__int128 int128_t
Signed 128 bit integer.
Definition architecture.hpp:54
constexpr bool is_numeric_unsigned_integral_v
Definition type_traits.hpp:61
variant_decay< T >::type variant_decay_t
Definition type_traits.hpp:614
constexpr bool is_byte_like_v
An array of this type will implicitly create objects within that array.
Definition type_traits.hpp:148
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:388
constexpr bool is_numeric_integral_v
Definition type_traits.hpp:85
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:493
constexpr bool is_character_v
Definition type_traits.hpp:130
constexpr bool is_numeric_signed_integral_v
Definition type_traits.hpp:42
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
Is a numeric signed integer.
Definition type_traits.hpp:32
Is a numeric unsigned integer.
Definition type_traits.hpp:51
Is a numeric integer.
Definition type_traits.hpp:71
Is a numeric.
Definition type_traits.hpp:96
Definition type_traits.hpp:115
An array of this type will implicitly create objects within that array.
Definition type_traits.hpp:136
type-trait to convert a character to a string type.
Definition type_traits.hpp:152
type-trait to convert a character to a string_view type.
Definition type_traits.hpp:165
Definition type_traits.hpp:178
Definition type_traits.hpp:186
Has an signed integer of a specific size, natively supported by the compiler.
Definition type_traits.hpp:206
Has an unsigned integer of a specific size, natively supported by the compiler.
Definition type_traits.hpp:211
Has an float of a specific size, natively supported by the compiler.
Definition type_traits.hpp:216
Has an signed integer of a specific size.
Definition type_traits.hpp:221
Has an unsigned integer of a specific size.
Definition type_traits.hpp:226
Has an float of a specific size.
Definition type_traits.hpp:232
Make an signed integer.
Definition type_traits.hpp:237
Make an unsigned integer.
Definition type_traits.hpp:242
Make an floating point.
Definition type_traits.hpp:247
Get an integer type that will fit all values from all template parameters.
Definition type_traits.hpp:302
Definition type_traits.hpp:355
Type-trait to copy const volatile qualifiers from one type to another.
Definition type_traits.hpp:363
Definition type_traits.hpp:391
Definition type_traits.hpp:402
Definition type_traits.hpp:413
Definition type_traits.hpp:419
Definition type_traits.hpp:425
Definition type_traits.hpp:437
Definition type_traits.hpp:446
Smart pointer traits.
Definition type_traits.hpp:459
void type
The type the pointer points to.
Definition type_traits.hpp:466
Is context a form of the expected type.
Definition type_traits.hpp:534
Definition type_traits.hpp:589
Decays types for use as elements in std::variant.
Definition type_traits.hpp:602
This selector allows access to member variable by name.
Definition type_traits.hpp:645
Documentation of a type.
Definition type_traits.hpp:665
Helper type to turn a set of lambdas into a single overloaded type to pass to std::visit().
Definition type_traits.hpp:674
A type traits for generating default values of a type.
Definition type_traits.hpp:687