header_utils
Loading...
Searching...
No Matches
named.h
1
4
5#pragma once
6
7#include <algorithm>
8#include <cmath>
9
10namespace ghassanpl
11{
12
13 namespace detail
14 {
15 template<size_t N>
16 struct FixedString
17 {
18 constexpr FixedString(char const (&s)[N]) { std::copy_n(s, N, this->elems); }
19 constexpr std::strong_ordering operator<=>(FixedString const&) const = default;
20 char elems[N];
21 };
22 }
23
24 namespace traits
25 {
26 struct addable {
27 template <typename SELF_TYPE, typename OTHERS_SELF_TYPE = SELF_TYPE>
28 //static constexpr bool applies_to = requires (SELF_TYPE::base_type a, std::remove_cvref_t<OTHERS_SELF_TYPE>::base_type b) { { a + b } -> std::convertible_to<SELF_TYPE::base_type>; };
29 static constexpr bool applies_to = true;
30 };
31 struct subtractable {
32 template <typename SELF_TYPE, typename OTHERS_SELF_TYPE = SELF_TYPE>
33 //static constexpr bool applies_to = requires (SELF_TYPE::base_type a, std::remove_cvref_t<OTHERS_SELF_TYPE>::base_type b) { { a - b } -> std::convertible_to<SELF_TYPE::base_type>; };
34 static constexpr bool applies_to = true;
35 };
36
37 struct incrementable {
38 template <typename SELF_TYPE>
39 static constexpr bool applies_to = true;
40 };
41
44 struct location { template <typename SELF_TYPE> static constexpr bool applies_to = true; };
45
48 struct displacement { template <typename SELF_TYPE> static constexpr bool applies_to = true; };
49
50 struct implicitly_convertible { template <typename SELF_TYPE> static constexpr bool applies_to = true; };
51 struct implicitly_constructible { template <typename SELF_TYPE> static constexpr bool applies_to = true; };
52 template <typename T>
53 struct implicitly_constructible_from { using type = T; template <typename SELF_TYPE> static constexpr bool applies_to = true; };
54
55 template <typename LOCATION_NAMED_TYPE>
56 struct is_displacement_of {
57 using location_type = LOCATION_NAMED_TYPE;
58 template <typename SELF_TYPE>
59 static constexpr bool applies_to = std::same_as<typename std::remove_cvref_t<LOCATION_NAMED_TYPE>::base_type, typename SELF_TYPE::base_type>;
60 };
61
62 template <typename DISPLACEMENT_NAMED_TYPE>
63 struct is_location_of {
64 using displacement_type = DISPLACEMENT_NAMED_TYPE;
65 template <typename SELF_TYPE>
66 static constexpr bool applies_to = std::same_as<typename std::remove_cvref_t<DISPLACEMENT_NAMED_TYPE>::base_type, typename SELF_TYPE::base_type>;
67 };
68
69 template <typename DISPLACEMENT_TYPE, typename LOCATION_TYPE>
70 concept named_is_displacement_of =
71 is_displacement_of<LOCATION_TYPE>::template applies_to<std::remove_cvref_t<DISPLACEMENT_TYPE>> ||
72 is_location_of<DISPLACEMENT_TYPE>::template applies_to<std::remove_cvref_t<LOCATION_TYPE>>
73 ;
74
75 template <typename NAMED_TYPE, typename TRAIT_TYPE>
76 concept applies_to = std::remove_cvref_t<NAMED_TYPE>::template has_trait<std::remove_cvref_t<TRAIT_TYPE>>;
77 }
78
79 template <typename T, detail::FixedString PARAMETER, typename... TRAITS>
80 struct named
81 {
82 using addable = traits::addable;
83 using subtractable = traits::subtractable;
84 using location = traits::location;
85 using displacement = traits::displacement;
86
87 using base_type = T;
88 using self_type = named<T, PARAMETER, TRAITS...>;
89 static constexpr detail::FixedString name = PARAMETER;
90
91 private:
92 template <typename U>
93 static constexpr auto find_displacement_type_impl(traits::is_location_of<U>)
94 {
95 return std::type_identity<std::remove_cvref_t<T>>{};
96 }
97 static constexpr auto find_displacement_type_impl(...)
98 {
99 return std::type_identity<void>{};
100 }
101
102 template <typename FIRST_TRAIT, typename... REST>
103 static constexpr auto find_displacement_type_traits(FIRST_TRAIT trait, REST... traits)
104 {
105 using type_candidate = std::remove_cvref_t<typename decltype(find_displacement_type_impl(trait))::type>;
106 if constexpr (std::is_same_v<type_candidate, void>)
107 return find_displacement_type_traits(traits...);
108 else
109 return std::type_identity<type_candidate>{};
110 }
111
112 static constexpr auto find_displacement_type_traits() { return std::type_identity<void>{}; }
113
114 static constexpr auto find_displacement_type()
115 {
116 return find_displacement_type_traits(TRAITS{}...);
117 }
118 public:
119
120 template <typename TRAIT, typename... OTHER>
121 static constexpr bool has_trait = (std::is_same_v<TRAIT, TRAITS> || ...) && TRAIT::template applies_to<self_type, OTHER...>;
122
123 using displacement_type = typename decltype(find_displacement_type())::type;
124
125 T value{};
126
127 template <typename... ARGS>
128 requires std::constructible_from<T, ARGS...>
129 constexpr explicit named(ARGS&&... args) noexcept(std::is_nothrow_constructible_v<T, ARGS...>) : value(std::forward<ARGS>(args)...) {}
130
131 template <typename U>
132 requires has_trait<traits::implicitly_constructible> && std::is_same_v<std::remove_cvref_t<U>, T>
133 constexpr named(U&& arg) noexcept(std::is_nothrow_move_constructible_v<T>)
134 : value(std::forward<U>(arg))
135 {
136 }
137
138 template <typename U>
140 constexpr named(U&& arg) noexcept(std::is_nothrow_move_constructible_v<T>)
141 : value((T)std::forward<U>(arg))
142 {
143 }
144
145 constexpr named() noexcept(std::is_nothrow_default_constructible_v<T>) = default;
150
152 requires requires(U&& val) { { named_cast<self_type>(std::forward<U>(val)) } -> std::same_as<self_type>; }
153 constexpr named(U&& arg)
154 : named(named_cast<self_type>(std::forward<U>(arg)))
155 {
156
157 }
158
159 constexpr T const& operator*() const & noexcept { return value; }
160 constexpr T operator*() && noexcept { return std::move(value); }
161
162 constexpr T* operator->() noexcept { return &value; }
163 constexpr T const* operator->() const noexcept { return &value; }
164
165 constexpr T& get() & noexcept { return value; }
166 constexpr T const& get() const& noexcept { return value; }
167 constexpr T get() && noexcept { return std::move(value); }
168
169 template <typename U>
170 constexpr U as() noexcept { return static_cast<U>(value); }
171
172 constexpr auto drop() noexcept(std::is_nothrow_move_constructible_v<T>) { return std::move(value); }
173
174 template <typename U, detail::FixedString OTHER_PARAMETER, typename... OTHER_CAPABILITIES>
175 requires requires(self_type const& self) { { named_cast<named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>>(self) } -> std::same_as<named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>>; }
176 constexpr operator named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>() const
177 {
178 return named_cast<named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>>(*this);
179 }
180
181 template <typename U>
182 requires requires(self_type const& self) { { named_cast<U>(self) } -> std::same_as<U>; }
183 constexpr explicit operator U() const
184 {
185 return named_cast<U>(*this);
186 }
187
188 constexpr explicit operator bool() const noexcept { return value; }
189 constexpr operator base_type() const noexcept requires has_trait<traits::implicitly_convertible> { return value; }
190
191 constexpr auto operator<=>(named const&) const = default;
192
193 template <typename U>
194 constexpr auto operator<=>(U const& b) const { return value <=> b; }
195 template <typename U>
196 constexpr bool operator==(U const& b) const { return value == b; }
197 //friend constexpr auto operator ==(T const& a, named const& b) { return a == b.value; }
198
199 constexpr named& operator++()
200 requires has_trait<traits::incrementable>
201 {
202 ++this->value;
203 return *this;
204 }
205
206 constexpr auto operator+(self_type const& val) const
208 {
209 return self_type{ this->value + val.value };
210 }
211
212 constexpr auto& operator+=(self_type const& val)
214 {
215 this->value += val.value;
216 return *this;
217 }
218
219 /*
220 constexpr auto operator-(self_type const& val) const
221 requires (has_trait<displacement> || has_trait<subtractable>) && (!has_trait<location>)
222 {
223 return self_type{ this->value - val.value };
224 }
225 */
226
227 friend constexpr auto operator-(self_type const& other, self_type const& self)
229 {
230 return self_type{ other.value - self.value };
231 }
232
234 constexpr auto operator-(self_type val) const
235 requires (has_trait<location>) && (!std::same_as<displacement_type, void>)
236 {
237 return displacement_type{ this->value - val.value };
238 }
239
241 template <typename LOCATION_TYPE>
242 constexpr auto operator+(LOCATION_TYPE&& val) const
243 requires
245 (traits::applies_to<LOCATION_TYPE, location>) &&
246 (traits::named_is_displacement_of<self_type, LOCATION_TYPE>) &&
247 (addable::applies_to<self_type, LOCATION_TYPE>)
248 {
249 return std::remove_cvref_t<LOCATION_TYPE>{ this->value + std::forward<LOCATION_TYPE>(val).value };
250 }
251
253 template <typename DISPLACEMENT_TYPE>
254 constexpr auto operator+(DISPLACEMENT_TYPE&& val) const
255 requires
257 (traits::applies_to<DISPLACEMENT_TYPE, displacement>) &&
258 (traits::named_is_displacement_of<DISPLACEMENT_TYPE, self_type>) &&
259 (addable::applies_to<self_type, DISPLACEMENT_TYPE>)
260 {
261 return self_type{ this->value + std::forward<DISPLACEMENT_TYPE>(val).value };
262 }
263
264 template <typename U>
265 constexpr auto operator*(U&& val) const
266 requires has_trait<displacement> && std::constructible_from<T, decltype(std::declval<T>() * std::declval<U>())>
267 {
268 return self_type{ this->value * std::forward<U>(val) };
269 }
270
271 template <typename U>
272 constexpr auto operator/(U&& val) const
273 requires has_trait<displacement> && std::constructible_from<T, decltype(std::declval<T>() / std::declval<U>())>
274 {
275 return self_type{ this->value / std::forward<U>(val) };
276 }
277
278 constexpr auto operator/(self_type const& val) const
280 {
281 return this->value / val.value;
282 }
283
284 private:
285
286 };
287
288 static_assert(std::is_trivially_copyable_v<named<int, "int">> == std::is_trivially_copyable_v<int>);
289
290 namespace detail {
291 template <typename U, detail::FixedString OTHER_PARAMETER, typename... OTHER_CAPABILITIES>
292 static constexpr bool is_named_impl(std::type_identity<named<U, OTHER_PARAMETER, OTHER_CAPABILITIES...>>) { return true; }
293 static constexpr bool is_named_impl(...) { return false; }
294 }
295 template <typename OTHER>
296 static constexpr bool is_named_v = ::ghassanpl::detail::is_named_impl(std::type_identity<std::remove_cvref_t<OTHER>>{});
297
298
299 template <typename T, detail::FixedString PARAMETER, typename STRINGIFIER>
300 auto stringify(STRINGIFIER& str, named<T, PARAMETER> const& val)
301 {
302 return str(val.value);
303 }
304
305 template <typename ALPHA, typename T, detail::FixedString PARAMETER, typename... TRAITS>
307 {
308 using std::lerp;
309 return named<T, PARAMETER, TRAITS...>{ lerp(value_a.value, value_b.value, std::forward<ALPHA>(alpha)) };
310 }
311
312#define ghassanpl_named_string_literal(named_name, suffix) \
313 inline named_name operator"" suffix(const char* str, std::size_t len) { \
314 return named_name{named_name::base_type{str,len}}; \
315 }
316
317#define ghassanpl_named_string_literal_ce(named_name, suffix) \
318 constexpr ghassanpl_named_string_literal(named_name, suffix)
319
320}
constexpr auto bit_count
Equal to the number of bits in the type.
Definition bits.h:33
nlohmann::json const & get(nlohmann::json const &g, std::string_view key, jtype type=jtype::discarded)
Gets the item in the json object g with the key key, or an empty json object if none found.
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
This trait implies the named type is an linear type, that is, a type that has the addition operator d...
Definition named.h:48
This trait implies the named type is an affine type, that is, a type that does not have the addition ...
Definition named.h:44