header_utils
Loading...
Searching...
No Matches
cpp23.h
1
4
5#pragma once
6
7#if defined(__cpp_lib_byteswap) && __cpp_lib_byteswap >= 202110L
8#include <bit>
9#endif
10#if defined(__cpp_lib_forward_like)
11#include <utility>
12#endif
13
14namespace ghassanpl
15{
16
17 template <class T, class... TYPES>
18 constexpr inline bool is_any_of_v = std::disjunction_v<std::is_same<T, TYPES>...>;
19
20 namespace detail
21 {
22 template <class _Ty>
23 using with_reference = _Ty&;
24
25 template <class T>
26 concept can_reference = requires { typename with_reference<T>; };
27 }
28
29 template <class T>
30 concept dereferenceable = requires(T & t) {
31 { *t } -> detail::can_reference;
32 };
33
34#if defined(__cpp_lib_forward_like)
35 using std::forward_like;
36#else
37 template <class Ty, class Uty>
38 [[nodiscard]] [[msvc::intrinsic]] constexpr auto&& forward_like(Uty&& Ux) noexcept
39 {
40 static_assert(detail::can_reference<Ty>, "forward_like's first template argument must be a referenceable type.");
41
42 using UnrefT = std::remove_reference_t<Ty>;
43 using UnrefU = std::remove_reference_t<Uty>;
44 if constexpr (std::is_const_v<UnrefT>) {
45 if constexpr (std::is_lvalue_reference_v<Ty>) {
46 return static_cast<const UnrefU&>(Ux);
47 }
48 else {
49 return static_cast<const UnrefU&&>(Ux);
50 }
51 }
52 else {
53 if constexpr (std::is_lvalue_reference_v<Ty>) {
54 return static_cast<UnrefU&>(Ux);
55 }
56 else {
57 return static_cast<UnrefU&&>(Ux);
58 }
59 }
60 }
61#endif
62
63#if __cpp_lib_byteswap < 202110L
64 template <class>
65 inline constexpr bool always_false = false;
66
67 [[nodiscard]] constexpr unsigned short byteswap_ushort(const unsigned short val) noexcept {
68 return static_cast<unsigned short>((val << 8) | (val >> 8));
69 }
70
71 [[nodiscard]] constexpr unsigned long byteswap_ulong(const unsigned long val) noexcept {
72 return (val << 24) | ((val << 8) & 0x00FF'0000) | ((val >> 8) & 0x0000'FF00) | (val >> 24);
73 }
74
75 [[nodiscard]] constexpr unsigned long long byteswap_uint64(const unsigned long long val) noexcept {
76 return (val << 56) | ((val << 40) & 0x00FF'0000'0000'0000) | ((val << 24) & 0x0000'FF00'0000'0000)
77 | ((val << 8) & 0x0000'00FF'0000'0000) | ((val >> 8) & 0x0000'0000'FF00'0000)
78 | ((val >> 24) & 0x0000'0000'00FF'0000) | ((val >> 40) & 0x0000'0000'0000'FF00) | (val >> 56);
79 }
80
81 template <class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
82 [[nodiscard]] constexpr T byteswap(const T val) noexcept
83 {
84 if constexpr (sizeof(T) == 1)
85 return val;
86 else if constexpr (sizeof(T) == 2)
87 return static_cast<T>(byteswap_ushort(static_cast<unsigned short>(val)));
88 else if constexpr (sizeof(T) == 4)
89 return static_cast<T>(byteswap_ulong(static_cast<unsigned long>(val)));
90 else if constexpr (sizeof(T) == 8)
91 return static_cast<T>(byteswap_uint64(static_cast<unsigned long long>(val)));
92 else
93 static_assert(always_false<T>, "unsupported integer size");
94 }
95#else
96 using std::byteswap;
97#endif
98}
constexpr auto bit_count
Equal to the number of bits in the type.
Definition bits.h:33
The below code is based on Sun's libm library code, which is licensed under the following license:
Primary namespace for everything in this library.
Definition align+rec2.h:10