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#include <memory>
14
15#include "min-cpp-version/cpp20.h"
16
17namespace ghassanpl
18{
19
20 template <class T, class = void>
21 struct is_complete : std::false_type
22 {
23 };
24
25 template <class T>
26 struct is_complete<T, decltype(void(sizeof(T)))> : std::true_type
27 {
28 };
29
30 template <class T>
31 concept is_complete_v = is_complete<T>::value;
32
33 template<class T, class U>
34 constexpr std::unique_ptr<T> dynamic_pointer_cast(std::unique_ptr<U>&& r) noexcept
35 {
36 if (auto p = dynamic_cast<T*>(r.get()))
37 return (void)r.release(), std::unique_ptr<T>(p);
38 else
39 return nullptr;
40 }
41
42 template<class T, class U>
43 constexpr std::unique_ptr<T> dynamic_steal_cast(std::unique_ptr<U>& r) noexcept
44 {
45 if (auto p = dynamic_cast<T*>(r.get()))
46 return (void)r.release(), std::unique_ptr<T>(p);
47 else
48 return nullptr;
49 }
50
51 template<class T, class D, class U>
52 constexpr std::unique_ptr<T, D> dynamic_pointer_cast(std::unique_ptr<U, D>&& r) noexcept
53 {
54 if (auto p = dynamic_cast<std::unique_ptr<T, D>::pointer>(r.get()))
55 return (void)r.release(), std::unique_ptr<T, D>(p, std::forward<D>(r.get_deleter()));
56 else if constexpr (!std::is_pointer_v<D> && std::is_default_constructible_v<D>)
57 return nullptr;
58 else if constexpr (std::is_copy_constructible_v<D>)
59 return std::unique_ptr<T, D>(nullptr, r.get_deleter());
60 }
61
62 template<class T, class U>
63 constexpr std::unique_ptr<T> static_pointer_cast(std::unique_ptr<U>&& r) noexcept
64 {
65 return std::unique_ptr<T>(static_cast<T*>(r.release()));
66 }
67
68 template<class T, class D, class U>
69 constexpr std::unique_ptr<T, D> static_pointer_cast(std::unique_ptr<U, D>&& r) noexcept
70 {
71 return std::unique_ptr<T, D>(r.release(), std::forward<D>(r.get_deleter()));
72 }
73
74#if defined(__cpp_concepts)
75 namespace detail
76 {
77 template <class _Ty>
78 using with_reference = _Ty&;
79
80 template <class T>
81 concept can_reference = requires { typename with_reference<T>; };
82 }
83
84 template <class T>
85 concept dereferenceable = requires(T & t) {
86 { *t } -> detail::can_reference;
87 };
88#endif
89
90#if defined(__cpp_lib_forward_like)
91 using std::forward_like;
92#else
93 template <class Ty, class Uty>
94 [[nodiscard]] constexpr auto&& forward_like(Uty&& Ux) noexcept
95 {
96 static_assert(detail::can_reference<Ty>, "forward_like's first template argument must be a referenceable type.");
97
98 using UnrefT = std::remove_reference_t<Ty>;
99 using UnrefU = std::remove_reference_t<Uty>;
100 if constexpr (std::is_const_v<UnrefT>) {
101 if constexpr (std::is_lvalue_reference_v<Ty>) {
102 return static_cast<const UnrefU&>(Ux);
103 }
104 else {
105 return static_cast<const UnrefU&&>(Ux);
106 }
107 }
108 else {
109 if constexpr (std::is_lvalue_reference_v<Ty>) {
110 return static_cast<UnrefU&>(Ux);
111 }
112 else {
113 return static_cast<UnrefU&&>(Ux);
114 }
115 }
116 }
117#endif
118
119#if __cpp_lib_byteswap < 202110L
120
121 [[nodiscard]] constexpr unsigned short byteswap_ushort(const unsigned short val) noexcept {
122 return static_cast<unsigned short>((val << 8) | (val >> 8));
123 }
124
125 [[nodiscard]] constexpr unsigned long byteswap_ulong(const unsigned long val) noexcept {
126 return (val << 24) | ((val << 8) & 0x00FF'0000) | ((val >> 8) & 0x0000'FF00) | (val >> 24);
127 }
128
129 [[nodiscard]] constexpr unsigned long long byteswap_uint64(const unsigned long long val) noexcept {
130 return (val << 56) | ((val << 40) & 0x00FF'0000'0000'0000) | ((val << 24) & 0x0000'FF00'0000'0000)
131 | ((val << 8) & 0x0000'00FF'0000'0000) | ((val >> 8) & 0x0000'0000'FF00'0000)
132 | ((val >> 24) & 0x0000'0000'00FF'0000) | ((val >> 40) & 0x0000'0000'0000'FF00) | (val >> 56);
133 }
134
135 template <class T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
136 [[nodiscard]] constexpr T byteswap(const T val) noexcept
137 {
138 if constexpr (sizeof(T) == 1)
139 return val;
140 else if constexpr (sizeof(T) == 2)
141 return static_cast<T>(byteswap_ushort(static_cast<unsigned short>(val)));
142 else if constexpr (sizeof(T) == 4)
143 return static_cast<T>(byteswap_ulong(static_cast<unsigned long>(val)));
144 else if constexpr (sizeof(T) == 8)
145 return static_cast<T>(byteswap_uint64(static_cast<unsigned long long>(val)));
146 else
147 static_assert(always_false<T>, "unsupported integer size");
148 }
149#else
150 using std::byteswap;
151#endif
152
153#if defined(__cpp_lib_unreachable)
154 using std::unreachable;
155#else
156 [[noreturn]] inline void unreachable() noexcept
157 {
158 __assume(false);
159 }
160#endif
161}
Primary namespace for everything in this library.
Definition align+rec2.h:10