HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
tagged_id.hpp
1// Copyright Take Vos 2020.
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
5#pragma once
6
7#include "required.hpp"
8#include "cast.hpp"
9#include "math.hpp"
10#include "fixed_string.hpp"
11#include <limits>
12#include <typeinfo>
13#include <typeindex>
14
15namespace tt {
16
17template<typename T, basic_fixed_string Tag, ssize_t Max = std::numeric_limits<T>::max() - 1>
18class tagged_id {
19public:
20 static_assert(std::is_integral_v<T>, "Expecting tagged_id to be an integral");
21 static_assert(std::is_unsigned_v<T>, "Expecting tagged_id to be an unsigned integer");
22 static_assert(Max < std::numeric_limits<T>::max(), "Max must be at least one less than the maximum value of T");
23
24 using value_type = T;
25
26 constexpr static value_type max = Max;
27 constexpr static value_type invalid = max + 1;
28 constexpr static value_type mask = static_cast<value_type>((1ULL << std::bit_width(invalid)) - 1);
29
30 constexpr explicit tagged_id(signed long long rhs) noexcept : value(narrow_cast<value_type>(rhs))
31 {
32 tt_axiom(value <= invalid);
33 }
34 constexpr explicit tagged_id(signed long rhs) noexcept : value(narrow_cast<value_type>(rhs))
35 {
36 tt_axiom(value <= invalid);
37 }
38 constexpr explicit tagged_id(signed int rhs) noexcept : value(narrow_cast<value_type>(rhs))
39 {
40 tt_axiom(value <= invalid);
41 }
42 constexpr explicit tagged_id(signed short rhs) noexcept : value(narrow_cast<value_type>(rhs))
43 {
44 tt_axiom(value <= invalid);
45 }
46 constexpr explicit tagged_id(signed char rhs) noexcept : value(narrow_cast<value_type>(rhs))
47 {
48 tt_axiom(value <= invalid);
49 }
50 constexpr explicit tagged_id(unsigned long long rhs) noexcept : value(narrow_cast<value_type>(rhs))
51 {
52 tt_axiom(value <= invalid);
53 }
54 constexpr explicit tagged_id(unsigned long rhs) noexcept : value(narrow_cast<value_type>(rhs))
55 {
56 tt_axiom(value <= invalid);
57 }
58 constexpr explicit tagged_id(unsigned int rhs) noexcept : value(narrow_cast<value_type>(rhs))
59 {
60 tt_axiom(value <= invalid);
61 }
62 constexpr explicit tagged_id(unsigned short rhs) noexcept : value(narrow_cast<value_type>(rhs))
63 {
64 tt_axiom(value <= invalid);
65 }
66 constexpr explicit tagged_id(unsigned char rhs) noexcept : value(narrow_cast<value_type>(rhs))
67 {
68 tt_axiom(value <= invalid);
69 }
70
71 constexpr tagged_id &operator=(signed long long rhs) noexcept
72 {
73 value = narrow_cast<value_type>(rhs);
74 tt_axiom(value <= invalid);
75 return *this;
76 }
77 constexpr tagged_id &operator=(signed long rhs) noexcept
78 {
79 value = narrow_cast<value_type>(rhs);
80 tt_axiom(value <= invalid);
81 return *this;
82 }
83 constexpr tagged_id &operator=(signed int rhs) noexcept
84 {
85 value = narrow_cast<value_type>(rhs);
86 tt_axiom(value <= invalid);
87 return *this;
88 }
89 constexpr tagged_id &operator=(signed short rhs) noexcept
90 {
91 value = narrow_cast<value_type>(rhs);
92 tt_axiom(value <= invalid);
93 return *this;
94 }
95 constexpr tagged_id &operator=(signed char rhs) noexcept
96 {
97 value = narrow_cast<value_type>(rhs);
98 tt_axiom(value <= invalid);
99 return *this;
100 }
101 constexpr tagged_id &operator=(unsigned long long rhs) noexcept
102 {
103 value = narrow_cast<value_type>(rhs);
104 tt_axiom(value <= invalid);
105 return *this;
106 }
107 constexpr tagged_id &operator=(unsigned long rhs) noexcept
108 {
109 value = narrow_cast<value_type>(rhs);
110 tt_axiom(value <= invalid);
111 return *this;
112 }
113 constexpr tagged_id &operator=(unsigned int rhs) noexcept
114 {
115 value = narrow_cast<value_type>(rhs);
116 tt_axiom(value <= invalid);
117 return *this;
118 }
119 constexpr tagged_id &operator=(unsigned short rhs) noexcept
120 {
121 value = narrow_cast<value_type>(rhs);
122 tt_axiom(value <= invalid);
123 return *this;
124 }
125 constexpr tagged_id &operator=(unsigned char rhs) noexcept
126 {
127 value = narrow_cast<value_type>(rhs);
128 tt_axiom(value <= invalid);
129 return *this;
130 }
131
132 constexpr tagged_id() noexcept : value(invalid) {}
133 constexpr tagged_id(tagged_id const &other) noexcept = default;
134 constexpr tagged_id(tagged_id &&other) noexcept = default;
135 constexpr tagged_id &operator=(tagged_id const &other) noexcept = default;
136 constexpr tagged_id &operator=(tagged_id &&other) noexcept = default;
137
138 constexpr operator signed long long() const noexcept
139 {
140 return narrow_cast<signed long long>(value);
141 }
142 constexpr operator signed long() const noexcept
143 {
144 return narrow_cast<signed long>(value);
145 }
146 constexpr operator signed int() const noexcept
147 {
148 return narrow_cast<signed int>(value);
149 }
150 constexpr operator signed short() const noexcept
151 {
152 return narrow_cast<signed short>(value);
153 }
154 constexpr operator signed char() const noexcept
155 {
156 return narrow_cast<signed char>(value);
157 }
158 constexpr operator unsigned long long() const noexcept
159 {
160 return narrow_cast<unsigned long long>(value);
161 }
162 constexpr operator unsigned long() const noexcept
163 {
164 return narrow_cast<unsigned long>(value);
165 }
166 constexpr operator unsigned int() const noexcept
167 {
168 return narrow_cast<unsigned int>(value);
169 }
170 constexpr operator unsigned short() const noexcept
171 {
172 return narrow_cast<unsigned short>(value);
173 }
174 constexpr operator unsigned char() const noexcept
175 {
176 return narrow_cast<unsigned char>(value);
177 }
178
179 constexpr operator bool() const noexcept
180 {
181 return value <= max;
182 }
183
184 [[nodiscard]] constexpr size_t hash() const noexcept
185 {
186 return std::hash<value_type>{}(value);
187 }
188
189 [[nodiscard]] constexpr friend bool operator==(tagged_id const &lhs, tagged_id const &rhs) noexcept
190 {
191 return lhs.value == rhs.value;
192 }
193 [[nodiscard]] constexpr friend bool operator!=(tagged_id const &lhs, tagged_id const &rhs) noexcept
194 {
195 return lhs.value != rhs.value;
196 }
197 [[nodiscard]] constexpr friend bool operator<(tagged_id const &lhs, tagged_id const &rhs) noexcept
198 {
199 return lhs.value < rhs.value;
200 }
201 [[nodiscard]] constexpr friend bool operator>(tagged_id const &lhs, tagged_id const &rhs) noexcept
202 {
203 return lhs.value > rhs.value;
204 }
205 [[nodiscard]] constexpr friend bool operator<=(tagged_id const &lhs, tagged_id const &rhs) noexcept
206 {
207 return lhs.value <= rhs.value;
208 }
209 [[nodiscard]] constexpr friend bool operator>=(tagged_id const &lhs, tagged_id const &rhs) noexcept
210 {
211 return lhs.value >= rhs.value;
212 }
213
214 template<typename O>
215 [[nodiscard]] constexpr friend bool operator==(tagged_id const &lhs, O const &rhs) noexcept
216 {
217 return lhs == tagged_id{rhs};
218 }
219 template<typename O>
220 [[nodiscard]] constexpr friend bool operator!=(tagged_id const &lhs, O const &rhs) noexcept
221 {
222 return lhs != tagged_id{rhs};
223 }
224 template<typename O>
225 [[nodiscard]] constexpr friend bool operator<(tagged_id const &lhs, O const &rhs) noexcept
226 {
227 return lhs < tagged_id{rhs};
228 }
229 template<typename O>
230 [[nodiscard]] constexpr friend bool operator>(tagged_id const &lhs, O const &rhs) noexcept
231 {
232 return lhs > tagged_id{rhs};
233 }
234 template<typename O>
235 [[nodiscard]] constexpr friend bool operator<=(tagged_id const &lhs, O const &rhs) noexcept
236 {
237 return lhs <= tagged_id{rhs};
238 }
239 template<typename O>
240 [[nodiscard]] constexpr friend bool operator>=(tagged_id const &lhs, O const &rhs) noexcept
241 {
242 return lhs >= tagged_id{rhs};
243 }
244 template<typename O>
245 [[nodiscard]] constexpr friend bool operator==(O const &lhs, tagged_id const &rhs) noexcept
246 {
247 return tagged_id{lhs} == rhs;
248 }
249 template<typename O>
250 [[nodiscard]] constexpr friend bool operator!=(O const &lhs, tagged_id const &rhs) noexcept
251 {
252 return tagged_id{lhs} != rhs;
253 }
254 template<typename O>
255 [[nodiscard]] constexpr friend bool operator<(O const &lhs, tagged_id const &rhs) noexcept
256 {
257 return tagged_id{lhs} < rhs;
258 }
259 template<typename O>
260 [[nodiscard]] constexpr friend bool operator>(O const &lhs, tagged_id const &rhs) noexcept
261 {
262 return tagged_id{lhs} > rhs;
263 }
264 template<typename O>
265 [[nodiscard]] constexpr friend bool operator<=(O const &lhs, tagged_id const &rhs) noexcept
266 {
267 return tagged_id{lhs} <= rhs;
268 }
269 template<typename O>
270 [[nodiscard]] constexpr friend bool operator>=(O const &lhs, tagged_id const &rhs) noexcept
271 {
272 return tagged_id{lhs} >= rhs;
273 }
274
275 [[nodiscard]] friend std::string to_string(tagged_id const &rhs) noexcept
276 {
277 return std::format("{}:{}", Tag, rhs.value);
278 }
279
280 friend std::ostream &operator<<(std::ostream &lhs, tagged_id const &rhs)
281 {
282 return lhs << to_string(rhs);
283 }
284
285private:
286 value_type value;
287};
288
289} // namespace tt
290
291namespace std {
292
293template<typename T, tt::basic_fixed_string Tag, tt::ssize_t Max>
294struct hash<tt::tagged_id<T, Tag, Max>> {
295 [[nodiscard]] constexpr size_t operator()(tt::tagged_id<T, Tag, Max> const &rhs) const noexcept
296 {
297 return rhs.hash();
298 }
299};
300
301} // namespace std
STL namespace.
Definition tagged_id.hpp:18
T operator()(T... args)