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 {};
118
122template<typename T> inline constexpr bool is_character_v = is_character<T>::value;
123
126template<typename T> struct make_string { };
127template<> struct make_string<char> { using type = std::string; };
128template<> struct make_string<wchar_t> { using type = std::wstring; };
129template<> struct make_string<char8_t> { using type = std::u8string; };
130template<> struct make_string<char16_t> { using type = std::u16string; };
131template<> struct make_string<char32_t> { using type = std::u32string; };
132
135template<typename T> using make_string_t = typename make_string<T>::type;
136
139template<typename T> struct make_string_view { using type = void; };
140template<> struct make_string_view<char> { using type = std::string_view; };
141template<> struct make_string_view<wchar_t> { using type = std::wstring_view; };
142template<> struct make_string_view<char8_t> { using type = std::u8string_view; };
143template<> struct make_string_view<char16_t> { using type = std::u16string_view; };
144template<> struct make_string_view<char32_t> { using type = std::u32string_view; };
145
148template<typename T>
149using make_string_view_t = typename make_string_view<T>::type;
150
151template<typename T, typename U>
153 using type = decltype(static_cast<T>(0) + static_cast<U>(0));
154};
155
156template<typename T, typename U>
157using make_promote_t = typename make_promote<T,U>::type;
158
159template<typename T, typename Ei=void>
161 using type = uintmax_t;
162};
163
164template<std::unsigned_integral T>
165struct make_intmax<T> {
166 using type = uintmax_t;
167};
168
169template<std::signed_integral T>
170struct make_intmax<T> {
171 using type = intmax_t;
172};
173
174template<typename T>
175using make_intmax_t = typename make_intmax<T>::type;
176
180template<std::size_t N> struct has_intxx : public std::false_type {};
181
185template<std::size_t N> struct has_uintxx : public std::false_type {};
186
190template<std::size_t N> struct has_floatxx : public std::false_type {};
191
195template<std::size_t N> struct make_intxx {};
196
200template<std::size_t N> struct make_uintxx {};
201
205template<std::size_t N> struct make_floatxx {};
206
207#if (HI_COMPILER == HI_CC_CLANG || HI_COMPILER == HI_CC_GCC) && (HI_PROCESSOR == HI_CPU_X64)
208template<> struct has_intxx<128> : public std::true_type {};
209template<> struct has_uintxx<128> : public std::true_type {};
210template<> struct make_intxx<128> { using type = __int128; };
211template<> struct make_uintxx<128> { using type = unsigned __int128; };
212#endif
213template<> struct has_intxx<64> : public std::true_type {};
214template<> struct has_uintxx<64> : public std::true_type {};
215template<> struct has_floatxx<64> : public std::true_type {};
216template<> struct make_intxx<64> { using type = int64_t; };
217template<> struct make_uintxx<64> { using type = uint64_t; };
218template<> struct make_floatxx<64> { using type = double; };
219template<> struct has_intxx<32> : public std::true_type {};
220template<> struct has_uintxx<32> : public std::true_type {};
221template<> struct has_floatxx<32> : public std::true_type {};
222template<> struct make_intxx<32> { using type = int32_t; };
223template<> struct make_uintxx<32> { using type = uint32_t; };
224template<> struct make_floatxx<32> { using type = float; };
225template<> struct has_intxx<16> : public std::true_type {};
226template<> struct has_uintxx<16> : public std::true_type {};
227template<> struct make_intxx<16> { using type = int16_t; };
228template<> struct make_uintxx<16> { using type = uint16_t; };
229template<> struct has_intxx<8> : public std::true_type {};
230template<> struct has_uintxx<8> : public std::true_type {};
231template<> struct make_intxx<8> { using type = int8_t; };
232template<> struct make_uintxx<8> { using type = uint8_t; };
233
234template<std::size_t N> constexpr bool has_intxx_v = has_intxx<N>::value;
235template<std::size_t N> constexpr bool has_uintxx_v = has_uintxx<N>::value;
236template<std::size_t N> constexpr bool has_floatxx_v = has_floatxx<N>::value;
237template<std::size_t N> using make_intxx_t = typename make_intxx<N>::type;
238template<std::size_t N> using make_uintxx_t = typename make_uintxx<N>::type;
239template<std::size_t N> using make_floatxx_t = typename make_floatxx<N>::type;
240
253template<typename L, typename... R>
255
256template<std::integral T>
257struct common_integer<T,T> {
258 using type = T;
259};
260
261template<std::unsigned_integral L, std::unsigned_integral R>
262struct common_integer<L,R> {
263 using type = std::conditional_t<(sizeof(L) > sizeof(R)), L, R>;
264};
265
266template<std::signed_integral L, std::signed_integral R>
267struct common_integer<L,R> {
268 using type = std::conditional_t<(sizeof(L) > sizeof(R)), L, R>;
269};
270
271template<std::unsigned_integral L, std::signed_integral R>
272struct common_integer<L,R> {
273 using _left_type =
274 std::conditional_t<(sizeof(L) < sizeof(short)), short,
275 std::conditional_t<(sizeof(L) < sizeof(int)), int,
276 std::conditional_t<(sizeof(L) < sizeof(long)), long, long long>>>;
277
278 using type = common_integer<_left_type, R>::type;
279};
280
281template<std::signed_integral L, std::unsigned_integral R>
282struct common_integer<L,R> {
283 using type = common_integer<R, L>::type;
284};
285
286template<std::integral L, std::integral M, std::integral... R>
287struct common_integer<L, M, R...> {
288 using type = common_integer<L, typename common_integer<M, R...>::type>::type;
289};
290
303template<std::integral L, std::integral... R>
304using common_integer_t = common_integer<L, R...>::type;
305
306
309template<typename To, typename From, typename Ei=void>
310struct copy_cv {};
311
312template<typename To, typename From> requires(not std::is_const_v<From> and not std::is_volatile_v<From>)
314 using type = std::remove_cv_t<To>;
315};
316
317template<typename To, typename From> requires(not std::is_const_v<From> and std::is_volatile_v<From>)
318struct copy_cv<To,From> {
319 using type = std::remove_cv_t<To> volatile;
320};
321
322template<typename To, typename From> requires(std::is_const_v<From> and not std::is_volatile_v<From>)
323struct copy_cv<To,From> {
324 using type = std::remove_cv_t<To> const;
325};
326
327template<typename To, typename From> requires(std::is_const_v<From> and std::is_volatile_v<From>)
328struct copy_cv<To,From> {
329 using type = std::remove_cv_t<To> const volatile;
330};
331
334template<typename To, typename From>
336
337template <typename T> struct has_value_type
338{
339 template <typename C> static std::true_type test(typename C::value_type *);
340 template <typename> static std::false_type test(...);
341
342 static const bool value = std::is_same_v<decltype(test<T>(nullptr)), std::true_type>;
343};
344
345template<typename T>
346inline constexpr bool has_value_type_v = has_value_type<T>::value;
347
348template <typename T> struct has_add_callback
349{
350 template <typename C> static std::true_type test(decltype(&C::add_callback) func_ptr);
351 template <typename> static std::false_type test(...);
352
353 static const bool value = std::is_same_v<decltype(test<T>(nullptr)), std::true_type>;
354};
355
356template<typename T>
357inline constexpr bool has_add_callback_v = has_add_callback<T>::value;
358
359template<typename BaseType, typename DerivedType>
360struct is_decayed_base_of : public std::is_base_of<std::decay_t<BaseType>,std::decay_t<DerivedType>> {};
361
362template<typename BaseType, typename DerivedType>
363constexpr bool is_decayed_base_of_v = is_decayed_base_of<BaseType,DerivedType>::value;
364
365template<typename DerivedType, typename BaseType>
366struct is_derived_from : public std::is_base_of<BaseType,DerivedType> {};
367
368template<typename DerivedType, typename BaseType>
369constexpr bool is_derived_from_v = is_derived_from<DerivedType,BaseType>::value;
370
371template<typename DerivedType, typename BaseType>
372struct is_decayed_derived_from : public is_decayed_base_of<BaseType,DerivedType> {};
373
374template<typename DerivedType, typename BaseType>
375constexpr bool is_decayed_derived_from_v = is_decayed_derived_from<DerivedType,BaseType>::value;
376
380template<typename Context, typename Expected>
381constexpr bool is_different_v = not std::is_same_v<std::decay_t<Context>,std::decay_t<Expected>>;
382
383template<typename T>
384struct is_atomic : public std::false_type {};
385
386template<typename T>
387struct is_atomic<std::atomic<T>> : public std::true_type {};
388
389template<typename T>
390constexpr bool is_atomic_v = is_atomic<T>::value;
391
392template<typename First, typename Second>
393struct use_first {
394 using type = First;
395};
396
397template<typename First, typename Second>
399
405template<typename T>
409 constexpr static bool value = false;
410
413 using type = void;
414};
415
416template<typename T> struct smart_pointer_traits<std::shared_ptr<T>> {constexpr static bool value = true; using type = T;};
417template<typename T> struct smart_pointer_traits<std::weak_ptr<T>> {constexpr static bool value = true; using type = T;};
418template<typename T> struct smart_pointer_traits<std::unique_ptr<T>> {constexpr static bool value = true; using type = T;};
419template<typename T> struct smart_pointer_traits<T *> {constexpr static bool value = true; using type = T;};
420
428#define hi_call_method(object, method, ...) \
429 [&]() { \
430 if constexpr (smart_pointer_traits<std::decay_t<decltype(object)>>::value) { \
431 return object->method(__VA_ARGS__); \
432 } else { \
433 return object.method(__VA_ARGS__); \
434 } \
435 }()
436
439template<typename Out, typename In>
442
480template<typename Context, typename Expected, typename... OtherExpected>
482
483template<typename Context, typename Expected, typename FirstOtherExpected, typename... OtherExpected>
484struct is_forward_of<Context, Expected, FirstOtherExpected, OtherExpected...> : std::conditional_t<
485 is_forward_of<Context, Expected>::value or
486 (is_forward_of<Context, FirstOtherExpected>::value or ... or is_forward_of<Context, OtherExpected>::value),
487 std::true_type,
488 std::false_type> {};
489
490template<typename Context, typename Expected>
491struct is_forward_of<Context, Expected> :
492 std::conditional_t<
493 std::is_same_v<std::decay_t<Context>, Expected> or std::is_base_of_v<Expected, std::decay_t<Context>>,
494 std::true_type,
495 std::false_type> {
496 static_assert(not std::is_reference_v<Expected>, "Template argument Expected must be a non-reference type.");
497};
498
499template<typename Context, typename Expected>
500struct is_forward_of<Context, std::shared_ptr<Expected>> :
501 std::conditional_t<
502 std::is_convertible_v<Context, std::shared_ptr<Expected>>,
503 std::true_type,
504 std::false_type> {};
505
506template<typename Context, typename Expected>
507struct is_forward_of<Context, std::weak_ptr<Expected>> :
508 std::conditional_t<
509 std::is_convertible_v<Context, std::weak_ptr<Expected>>,
510 std::true_type,
511 std::false_type> {};
512
513template<typename Context, typename Expected>
514struct is_forward_of<Context, std::unique_ptr<Expected>> :
515 std::conditional_t<
516 std::is_convertible_v<Context, std::unique_ptr<Expected>>,
517 std::true_type,
518 std::false_type> {};
519
520template<typename Context, typename Expected>
521struct is_forward_of<Context, Expected *> :
522 std::conditional_t<
523 std::is_convertible_v<Context, Expected *>,
525 std::false_type> {};
526
527template<typename Context, typename Result, typename... Args>
528struct is_forward_of<Context, Result(Args...)> :
529 std::conditional_t<std::is_invocable_r_v<Result, Context, Args...>, std::true_type, std::false_type> {
530};
531
532template<typename Context, typename Expected, typename... OtherExpected>
533constexpr bool is_forward_of_v = is_forward_of<Context, Expected, OtherExpected...>::value;
534
539template<typename T>
541 using type = std::decay_t<T>;
542};
543
544template<>
545struct variant_decay<void> {
546 using type = std::monostate;
547};
548
551template<typename T>
552using variant_decay_t = variant_decay<T>::type;
553
582template<typename T>
583struct selector;
584
585
607template<typename T>
609
610
611
616template<class... Ts>
617struct overloaded : Ts... {
618 // Makes the call operator of each lambda available directly to the `overloaded` type.
619 using Ts::operator()...;
620
621 // The implicit constructor is all that is needed to initialize each lambda.
622};
623
624} // namespace hi::inline v1
Functions and macros for handling architectural difference between compilers, CPUs and operating syst...
STL namespace.
DOXYGEN BUG.
Definition algorithm.hpp:15
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:304
constexpr bool is_numeric_v
Definition type_traits.hpp:110
constexpr bool is_different_v
If the types are different.
Definition type_traits.hpp:381
typename make_string< T >::type make_string_t
type-trait to convert a character to a string type.
Definition type_traits.hpp:135
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:149
constexpr bool is_numeric_unsigned_integral_v
Definition type_traits.hpp:58
variant_decay< T >::type variant_decay_t
Definition type_traits.hpp:552
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:335
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 precision by numeric type Out.
Definition type_traits.hpp:440
constexpr bool is_character_v
Definition type_traits.hpp:122
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
type-trait to convert a character to a string type.
Definition type_traits.hpp:126
type-trait to convert a character to a string_view type.
Definition type_traits.hpp:139
Definition type_traits.hpp:152
Definition type_traits.hpp:160
Has an signed integer of a specific size.
Definition type_traits.hpp:180
Has an unsigned integer of a specific size.
Definition type_traits.hpp:185
Has an float of a specific size.
Definition type_traits.hpp:190
Make an signed integer.
Definition type_traits.hpp:195
Make an unsigned integer.
Definition type_traits.hpp:200
Make an floating point.
Definition type_traits.hpp:205
Get an integer type that will fit all values from all template parameters.
Definition type_traits.hpp:254
Type-trait to copy const volitile qualifiers from one type to another.
Definition type_traits.hpp:310
Definition type_traits.hpp:338
Definition type_traits.hpp:349
Definition type_traits.hpp:360
Definition type_traits.hpp:366
Definition type_traits.hpp:372
Definition type_traits.hpp:384
Definition type_traits.hpp:393
Smart pointer traits.
Definition type_traits.hpp:406
void type
The type the pointer points to.
Definition type_traits.hpp:413
Is context a form of the expected type.
Definition type_traits.hpp:481
Decays types for use as elements in std::variant.
Definition type_traits.hpp:540
This selector allows access to member variable by name.
Definition type_traits.hpp:583
Documentation of a type.
Definition type_traits.hpp:608
Helper type to turn a set of lambdas into a single overloaded type to pass to std::visit().
Definition type_traits.hpp:617