Gamp v0.0.7-54-gccdc599
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
enum_util.hpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this
9 * file, You can obtain one at https://opensource.org/license/mit/.
10 */
11
12#ifndef JAU_ENUM_UTIL_HPP_
13#define JAU_ENUM_UTIL_HPP_
14
15#include <array>
16#include <type_traits>
17#include <string_view>
18#include <cstring>
19#include <ostream>
20#include <jau/cpp_lang_util.hpp>
21
22/**
23 * Provides scoped enum type support functionality, including `to_string`,
24 * enum bitfield operations, etc.
25 *
26 * Due to lack of C++26 reflection,
27 * basic enum function definition is performed via macros to access value names outside constexpr templates.
28 *
29 * Overview
30 * - Define your `enum class` manually
31 * - Use one of the following `enum class` helper function generator
32 * - `JAU_MAKE_ENUM_STRING` for non-bitfield enum values
33 * - `JAU_MAKE_BITFIELD_ENUM_STRING` for bitfield enum values
34 * - `JAU_MAKE_ENUM_INFO` for typedef `E_info_t` with E enum class type using `enum_info<E, ...>`
35 * - `enum_info<E, ...>` provides iterator and further basic information for `E`
36 * - Following methods are made available via the generator `JAU_MAKE_ENUM_STRING`,
37 * assuming `E` is the enum class type
38 * - `constexpr std::string_view long_name(const E v) noexcept`
39 * - returns a long string, e.g. `E::value`
40 * - `constexpr std::string_view name(const E v) noexcept`
41 * - returns a short string, e.g. `value`
42 * - `constexpr std::string to_string(const E v)`
43 * - returns a short string, e.g. `value`.
44 * - Following methods are made available via the generator `JAU_MAKE_BITFIELD_ENUM_STRING`
45 * - all methods from `JAU_MAKE_ENUM_STRING`, while `to_string(const E v)` returns the set bit values, e.g. `[cat, mouse]`
46 * - General support `constexpr` template functions are available in the `jau::enums` namespace,
47 * assuming `E` is the enum class type, `v` an enum value and `U` the underlying type
48 * - `constexpr U number(const E v) noexcept`
49 * - returns the integral underlying value
50 * - `constexpr U operator*(const E v) noexcept`
51 * - this dereferencing overload operator also returns the integral underlying value like `number`
52 * - `constexpr bool is_set(const E mask, const E bits) noexcept`
53 * - returns `true` if mask contains given `bits`, otherwise `false`
54 * - `constexpr void append_bitstr(std::string& out, E mask, E bit, const std::string& bitstr, bool& comma)`
55 * - appends `bitstr` to `out` if `mask` contains `bit`, prepends a comma if `comma` and sets `comma` to `true`.
56 * - Equality- and bit-operations, e.g.
57 * - `constexpr bool operator==(const E lhs, const E rhs) noexcept`
58 * - `constexpr E operator&(const E lhs, const E rhs) noexcept`
59 * - `constexpr std::string_view long_name<auto v>() noexcept`
60 * - returns a long string, e.g. `E::value`
61 * - `constexpr std::string_view name<auto v>() noexcept`
62 * - returns a short string, e.g. `value`
63 * - `get_names`, `get_values`
64*/
65namespace jau::enums {
66
67 /** \addtogroup CppLang
68 *
69 * @{
70 */
71
72 ///
73 /// clang + gcc
74 ///
75
76 template<typename E, E V>
77 consteval_cxx20 const char* enum_funcname() noexcept {
78 // const char *enum_funcname() [E = test_type1_t, V = test_type1_t::one]
79 return JAU_PRETTY_FUNCTION;
80 }
81
82 template <auto V,
83 std::enable_if_t<std::is_enum_v<decltype(V)>>* = nullptr>
84 consteval_cxx20 bool is_enum() noexcept {
85 // bool is_name() [E = test_type_t, V = test_type_t::one]
86 constexpr std::string_view name(enum_funcname<decltype(V), V>());
87
88 size_t i = name.rfind(' ');
89 if ( std::string_view::npos == i || i+1 == name.length() ) {
90 return false;
91 }
92 ++i;
93 const char c = name[i];
94 return !(c >= '0' && c <= '9'); // true if character, not-a-number
95 }
96
97 template <auto V,
98 std::enable_if_t<std::is_enum_v<decltype(V)>>* = nullptr>
99 consteval_cxx20 std::string_view long_name() noexcept {
100 // const char *enum_funcname() [E = test_type1_t, V = test_type1_t::one]
101 constexpr std::string_view sym(enum_funcname<decltype(V), V>());
102 size_t i = sym.rfind(' ');
103 if ( std::string_view::npos == i || i+1 == sym.length() ) {
104 return sym;
105 }
106 ++i;
107 const char c = sym[i];
108 if ( c >= '0' && c <= '9' ) {
109 return sym;
110 }
111 if constexpr ( sym[sym.length() - 1] == ']' ) {
112 return sym.substr(i, sym.length()-i-1);
113 }
114 return sym.substr(i);
115 }
116
117 template <auto V,
118 std::enable_if_t<std::is_enum_v<decltype(V)>>* = nullptr>
119 consteval_cxx20 std::string_view name() noexcept {
120 // const char *enum_funcname() [E = test_type1_t, V = test_type1_t::one]
121 constexpr std::string_view sym(enum_funcname<decltype(V), V>());
122 // Find the final space character in the pretty name.
123 size_t i = sym.rfind(' ');
124 if ( std::string_view::npos == i || i+1 == sym.length() ) {
125 return sym;
126 }
127 ++i;
128 const char c = sym[i];
129 if ( c >= '0' && c <= '9' ) {
130 return sym;
131 }
132
133 size_t j = sym.find("::", i);
134 if ( std::string_view::npos == j || j+2 >= sym.length() ) {
135 return sym;
136 }
137 j+=2;
138 if constexpr ( sym[sym.length() - 1] == ']' ) {
139 return sym.substr(j, sym.length()-j-1);
140 }
141 return sym.substr(j);
142 }
143
144 template <auto... Vargs>
145 struct NameTable {
146 std::string_view names[sizeof...(Vargs)];
147 };
148 template <auto... Vargs>
149 consteval_cxx20 NameTable<Vargs...>
150 get_names() noexcept {
151 return { { long_name<Vargs>()... } };
152 }
153
154 template <typename E, size_t N>
155 struct ValueTable {
156 E values[N];
157 };
158 template <typename... Args>
159 constexpr ValueTable<std::common_type_t<Args...>, sizeof...(Args)>
160 get_values(Args... args) noexcept {
161 return { { args... } };
162 }
163
164 template <typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
165 constexpr std::underlying_type_t<E>
166 number(const E v) noexcept { return static_cast<std::underlying_type_t<E>>(v); }
167
168 template <typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
169 constexpr std::underlying_type_t<E>
170 operator*(const E v) noexcept { return static_cast<std::underlying_type_t<E>>(v); }
171
172 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
173 constexpr E operator~(const E rhs) noexcept {
174 return E(~number(rhs));
175 }
176
177 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
178 constexpr E operator^(const E lhs, const E rhs) noexcept {
179 return E(*lhs ^ *rhs);
180 }
181
182 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
183 constexpr E operator|(const E lhs, const E rhs) noexcept {
184 return E(*lhs | *rhs);
185 }
186
187 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
188 constexpr E operator&(const E lhs, const E rhs) noexcept {
189 return E(*lhs & *rhs);
190 }
191
192 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
193 constexpr E& operator|=(E& lhs, const E rhs) noexcept {
194 return lhs = lhs | rhs;
195 }
196
197 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
198 constexpr E& operator&=(E& lhs, const E rhs) noexcept {
199 return lhs = lhs & rhs;
200 }
201
202 /**
203 * If `set==true`, sets the `bits` in `store`, i.e. equivalent to `store |= bits` operation.
204 *
205 * Otherwise clears the `bits` in `store`, i.e. equivalent to `store &= ~bits` operation.
206 *
207 * Returns store reference.
208 */
209 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
210 constexpr E& write(E& store, const E bits, bool set) noexcept {
211 if( set ) {
212 return store = store | bits;
213 } else {
214 return store = store & ~bits;
215 }
216 }
217
218 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
219 constexpr E& operator^=(E& lhs, const E rhs) noexcept {
220 return lhs = lhs ^ rhs;
221 }
222
223 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
224 constexpr bool operator==(const E lhs, const E rhs) noexcept {
225 return *lhs == *rhs;
226 }
227
228 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
229 constexpr bool operator!=(const E lhs, const E rhs) noexcept {
230 return !(lhs == rhs);
231 }
232
233 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
234 constexpr bool is_set(const E mask, const E bits) noexcept {
235 return bits == (mask & bits);
236 }
237
238 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
239 constexpr bool has_any(const E mask, const E bits) noexcept {
240 return std::underlying_type_t<E>(0) != ( *mask & *bits );
241 }
242
243 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
244 constexpr bool has_any(const E mask) noexcept {
245 return std::underlying_type_t<E>(0) != ( *mask );
246 }
247
248 template<typename E, std::enable_if_t<std::is_enum_v<E>>* = nullptr>
249 constexpr void append_bitstr(std::string& out, E mask, E bit, const std::string& bitstr, bool& comma) {
250 if( bit == (mask & bit) ) {
251 if( comma ) { out.append(", "); }
252 out.append(bitstr); comma = true;
253 }
254 }
255
256 template <typename T,
257 std::enable_if_t<std::is_enum_v<T>>* = nullptr>
258 inline std::ostream& operator<<(std::ostream& os, const T v) { return os << name(v); }
259
260 template <typename EnumType, auto... Vargs> class enum_iterator; // fwd
261
262 /**
263 * Enumeration info template class including iterator (enum_iterator)
264 */
265 template <typename EnumType, auto... Vargs>
266 class enum_info {
267 public:
268 typedef size_t size_type;
269 typedef ssize_t difference_type;
270
271 /// enum value type, i.e. the enum type itself
272 typedef EnumType value_type;
273
274 /// pointer to value_type
275 typedef const value_type* pointer;
276 /// reference to value_type
277 typedef const value_type& reference;
278
279 /// enum_iterator to iterate over all enum values (const enum values)
281 /// enum_iterator to iterate over all enum values (const enum values)
283
284 /** Used to determine whether this type is an enum_info, see is_enum_info<T> */
285 typedef bool enum_info_tag;
286
287 /// array type for all enum values (value_type), see size()
288 typedef std::array<value_type, sizeof...(Vargs)> value_array_t;
289
290 /// number of all enum values
291 static constexpr size_type size() noexcept { return sizeof...(Vargs); }
292
293 private:
294 typedef const value_type* iterator_base_t;
295 value_array_t values_;
296 constexpr iterator_base_t begin_iter() const noexcept { return &values_[0]; }
297 constexpr iterator_base_t end_iter() const noexcept { return &values_[0] + size(); }
298 friend class enum_iterator<value_type, Vargs...>;
299
300 constexpr explicit enum_info() noexcept
301 : values_({{ Vargs... }})
302 { }
303
304 public:
305 constexpr enum_info(const enum_info& o) noexcept = delete;
306
307 constexpr_cxx23 static const enum_info& get() noexcept {
308 static enum_info singleton;
309 return singleton;
310 }
311
312 constexpr std::string_view name() const noexcept { return type_name(*begin()); }
313 constexpr value_array_t values() const noexcept { return values_; }
314
315 constexpr const_iterator cbegin() const noexcept { return const_iterator(*this, begin_iter()); }
316 constexpr const_iterator cend() const noexcept { return const_iterator(*this, end_iter()); }
317
318 constexpr iterator begin() const noexcept { return const_iterator(*this, begin_iter()); }
319 constexpr iterator end() const noexcept { return const_iterator(*this, end_iter()); }
320 };
321
322 /**
323 * <code>template< class T > is_enum_info<T>::value</code> compile-time Type Trait,
324 * determining whether the given template class is a enum_info type.
325 */
326 template< class, class = void >
327 struct is_enum_info : std::false_type { };
328
329 /**
330 * <code>template< class T > is_enum_info<T>::value</code> compile-time Type Trait,
331 * determining whether the given template class is a enum_info type.
332 */
333 template< class T >
334 struct is_enum_info<T, std::void_t<typename T::enum_info_tag>> : std::true_type { };
335
336 template <typename enum_info_t, std::enable_if_t<is_enum_info<enum_info_t>::value>* = nullptr>
337 inline std::ostream& operator<<(std::ostream& os, const enum_info_t& v) {
338 os << v.name() << "[";
339 typename enum_info_t::iterator end = v.end();
340 bool comma = false;
341 for(typename enum_info_t::iterator iter = v.begin(); iter != end; ++iter, comma=true) {
342 typename enum_info_t::value_type ev = *iter;
343 if( comma ) {
344 os << ", ";
345 }
346 os << ev << " (" << std::to_string( *ev ) << ")";
347 }
348 os << "]";
349 return os;
350 }
351
352 /**
353 * Enumeration iterator, see enum_info
354 */
355 template <typename EnumType, auto... Vargs>
356 class enum_iterator {
357 public:
358 typedef enum_info<EnumType, Vargs...> enum_info_t;
359
362
363 /// enum value type, i.e. the enum type itself
365
366 /// pointer to value_type
368
369 /// reference to value_type
371
372 /// enum_iterator to iterate over all enum values (const enum values)
373 typedef enum_info_t::iterator_base_t iterator_type;
374
375 private:
376 const enum_info_t& info_;
377 iterator_type iterator_;
378 friend class enum_info<EnumType, Vargs...>;
379
380 constexpr explicit enum_iterator(const enum_info_t& info, iterator_type iter) noexcept
381 : info_(info), iterator_(iter)
382 { }
383
384 public:
385 /**
386 * C++ named requirements: LegacyIterator: CopyConstructible
387 */
388 constexpr enum_iterator(const enum_iterator& o) noexcept = default;
389
390 /**
391 * Assigns content of other mutable iterator to this one,
392 * if they are not identical.
393 * <p>
394 * C++ named requirements: LegacyIterator: CopyAssignable
395 * </p>
396 * @param o the new identity value to be copied into this iterator
397 * @return reference to this
398 */
399 constexpr enum_iterator& operator=(const enum_iterator& o) noexcept = default;
400
401
402 /**
403 * C++ named requirements: LegacyIterator: MoveConstructable
404 */
405 constexpr enum_iterator(enum_iterator && o) noexcept = default;
406
407 /**
408 * Assigns identity of given mutable iterator,
409 * if they are not identical.
410 * <p>
411 * C++ named requirements: LegacyIterator: MoveAssignable
412 * </p>
413 * @param o the new identity to be taken
414 * @return reference to this
415 */
416 constexpr enum_iterator& operator=(enum_iterator&& o) noexcept = default;
417
418 const enum_info_t& description() const noexcept { return info_; }
419
420 /**
421 * C++ named requirements: LegacyIterator: Swappable
422 */
423 void swap(enum_iterator& o) noexcept {
424 std::swap( info_, o.info_);
425 std::swap( iterator_, o.iterator_);
426 }
427
428 /**
429 * Returns the distance to_end() using zero as first index. A.k.a the remaining elements iterable.
430 */
431 constexpr difference_type dist_end() const noexcept { return info_.end_iter() - iterator_; }
432
433 /**
434 * Returns true, if this iterator points to end().
435 */
436 constexpr bool is_end() const noexcept { return iterator_ == info_.end_iter(); }
437
438 /**
439 * This iterator is set to the last element, end(). Returns *this;
440 */
441 constexpr enum_iterator& to_end() noexcept
442 { iterator_ = info_.end_iter(); return *this; }
443
444 /**
445 * Returns the distance to_begin() using zero as first index. A.k.a the index from start.
446 */
447 constexpr difference_type dist_begin() const noexcept { return iterator_ - info_.begin_iter(); }
448
449 /**
450 * Returns true, if this iterator points to begin().
451 */
452 constexpr bool is_begin() const noexcept { return iterator_ == info_.begin_iter(); }
453
454 /**
455 * This iterator is set to the first element, begin(). Returns *this;
456 */
457 constexpr enum_iterator& to_begin() noexcept
458 { iterator_ = info_.begin_iter(); return *this; }
459
460 /**
461 * Returns a copy of the underlying storage iterator.
462 */
463 constexpr iterator_type base() const noexcept { return iterator_; }
464
465 // Multipass guarantee equality
466
467 /**
468 * Returns signum or three-way comparison value
469 * <pre>
470 * 0 if equal (both, store and iteratore),
471 * -1 if this->iterator_ < rhs_iter and
472 * 1 if this->iterator_ > rhs_iter (otherwise)
473 * </pre>
474 * @param rhs_store right-hand side store
475 * @param rhs_iter right-hand side iterator
476 */
477 constexpr int compare(const enum_iterator& rhs) const noexcept {
478 return iterator_ == rhs.iterator_ ? 0
479 : ( iterator_ < rhs.iterator_ ? -1 : 1);
480 }
481
482 /** Two way comparison operator, `!=` is implicit, C++20 */
483 constexpr bool operator==(const enum_iterator& rhs) const noexcept
484 { return iterator_ == rhs.iterator_; }
485
486 /** Three way std::strong_ordering comparison operator, C++20 */
487 std::strong_ordering operator<=>(const enum_iterator& rhs) const noexcept {
488 return iterator_ == rhs.iterator_ ? std::strong_ordering::equal :
489 ( iterator_ < rhs.iterator_ ? std::strong_ordering::less : std::strong_ordering::greater );
490 }
491
492 // Forward iterator requirements
493
494 /**
495 * Dereferencing iterator to value_type reference
496 * @return immutable reference to value_type
497 */
498 constexpr value_type operator*() const noexcept {
499 return *iterator_;
500 }
501
502 /**
503 * Pointer to member access.
504 * @return immutable pointer to value_type
505 */
506 constexpr const pointer operator->() const noexcept {
507 return &(*iterator_); // just in case iterator_type is a class, trick via dereference
508 }
509
510 /** Pre-increment; Well performing, return *this. */
511 constexpr enum_iterator& operator++() noexcept {
512 ++iterator_;
513 return *this;
514 }
515
516 /** Post-increment. */
517 constexpr enum_iterator operator++(int) noexcept
518 { return enum_iterator(info_, iterator_++); }
519
520 // Bidirectional iterator requirements
521
522 /** Pre-decrement; Well performing, return *this. */
523 constexpr enum_iterator& operator--() noexcept {
524 --iterator_;
525 return *this;
526 }
527
528 /** Post-decrement. */
529 constexpr enum_iterator operator--(int) noexcept
530 { return enum_iterator(info_, iterator_--); }
531
532 // Random access iterator requirements
533
534 /** Subscript of 'element_index', returning immutable value_type. */
535 constexpr value_type operator[](difference_type i) const noexcept
536 { return iterator_[i]; }
537
538 /** Addition-assignment of 'element_count'; Returns *this. */
539 constexpr enum_iterator& operator+=(difference_type i) noexcept
540 { iterator_ += i; return *this; }
541
542 /** Binary 'iterator + element_count' */
543 constexpr enum_iterator operator+(difference_type rhs) const noexcept
544 { return enum_iterator(info_, iterator_ + rhs); }
545
546 /** Subtraction-assignment of 'element_count'; Returns *this. */
547 constexpr enum_iterator& operator-=(difference_type i) noexcept
548 { iterator_ -= i; return *this; }
549
550 /** Binary 'iterator - element_count' */
551 constexpr enum_iterator operator-(difference_type rhs) const noexcept
552 { return enum_iterator(info_, iterator_ - rhs); }
553
554 // Distance or element count, binary subtraction of two iterator.
555
556 /** Binary 'iterator - iterator -> element_count'; Returns element_count of type difference_type. */
557 constexpr difference_type operator-(const enum_iterator& rhs) const noexcept
558 { return iterator_ - rhs.iterator_; }
559 };
560
561 /**@}*/
562
563} // namespace jau::enums
564
565/** \addtogroup CppLang
566 *
567 * @{
568 */
569
570//
571// JAU_FOR_EACH macros inspired by David Mazières, June 2021
572// <https://www.scs.stanford.edu/~dm/blog/va-opt.html>
573//
574// All hacks below to circumvent lack of C++26 reflection.
575//
576
577// Note space before (), so object-like macro
578#define JAU_PARENS ()
579
580#define JAU_EXPAND(...) JAU_EXPAND4(JAU_EXPAND4(JAU_EXPAND4(JAU_EXPAND4(__VA_ARGS__))))
581#define JAU_EXPAND4(...) JAU_EXPAND3(JAU_EXPAND3(JAU_EXPAND3(JAU_EXPAND3(__VA_ARGS__))))
582#define JAU_EXPAND3(...) JAU_EXPAND2(JAU_EXPAND2(JAU_EXPAND2(JAU_EXPAND2(__VA_ARGS__))))
583#define JAU_EXPAND2(...) JAU_EXPAND1(JAU_EXPAND1(JAU_EXPAND1(JAU_EXPAND1(__VA_ARGS__))))
584#define JAU_EXPAND1(...) __VA_ARGS__
585
586#define JAU_FOR_EACH(macro, type, ...) \
587 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH_HELPER(macro, type, __VA_ARGS__)))
588#define JAU_FOR_EACH_HELPER(macro, type, a1, ...) \
589 macro(type, a1) \
590 __VA_OPT__(JAU_FOR_EACH_AGAIN JAU_PARENS (macro, type, __VA_ARGS__))
591#define JAU_FOR_EACH_AGAIN() JAU_FOR_EACH_HELPER
592
593#define JAU_ENUM_CASE_SHORT(type, name) case type::name: return #name;
594#define JAU_ENUM_CASE_LONG(type, name) case type::name: return #type "::" #name;
595
596#define JAU_FOR_EACH_LIST(macro, type, ...) \
597 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH_LIST_HELPER(macro, type, __VA_ARGS__)))
598#define JAU_FOR_EACH_LIST_HELPER(macro, type, a1, ...) \
599 macro(type, a1) \
600 __VA_OPT__(, JAU_FOR_EACH_LIST_AGAIN JAU_PARENS (macro, type, __VA_ARGS__))
601#define JAU_FOR_EACH_LIST_AGAIN() JAU_FOR_EACH_LIST_HELPER
602
603#define JAU_ENUM_TYPE_VALUE(type, name) type::name
604#define JAU_ENUM_VALUE(type, name) name
605
606#define JAU_FOR_EACH_VALUE(macro, type, value, ...) \
607 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH_VALUE_HELPER(macro, type, value, __VA_ARGS__)))
608#define JAU_FOR_EACH_VALUE_HELPER(macro, type, value, a1, ...) \
609 macro(type, a1, value) \
610 __VA_OPT__(JAU_FOR_EACH_VALUE_AGAIN JAU_PARENS (macro, type, value, __VA_ARGS__))
611#define JAU_FOR_EACH_VALUE_AGAIN() JAU_FOR_EACH_VALUE_HELPER
612
613#define JAU_MAKE_ENUM_STRING(type, ...) \
614 JAU_MAKE_ENUM_STRING_SUB(type, type, __VA_ARGS__) \
615 \
616 constexpr std::string \
617 to_string(const type e) noexcept \
618 { return std::string(name(e)); } \
619
620#define JAU_APPEND_BITSTR(U,V,M) jau::enums::append_bitstr(out, M, U::V, #V, comma);
621
622#define JAU_MAKE_BITFIELD_ENUM_STRING(type, ...) \
623 JAU_MAKE_ENUM_STRING_SUB(type, type, __VA_ARGS__) \
624 \
625 inline std::string \
626 to_string(const type mask) noexcept { \
627 std::string out("["); \
628 bool comma = false; \
629 JAU_FOR_EACH_VALUE(JAU_APPEND_BITSTR, type, mask, __VA_ARGS__); \
630 out.append("]"); \
631 return out; \
632 } \
633
634#define JAU_MAKE_BITFIELD_ENUM_STRING2(type, stype, ...) \
635 JAU_MAKE_ENUM_STRING_SUB(type, stype, __VA_ARGS__) \
636 \
637 inline std::string \
638 to_string(const type mask) noexcept { \
639 std::string out("["); \
640 bool comma = false; \
641 JAU_FOR_EACH_VALUE(JAU_APPEND_BITSTR, type, mask, __VA_ARGS__); \
642 out.append("]"); \
643 return out; \
644 } \
645
646// internal usage only
647#define JAU_MAKE_ENUM_STRING_SUB(type, stype, ...) \
648 constexpr std::string_view \
649 long_name(const type v) noexcept \
650 { \
651 switch (v) { \
652 JAU_FOR_EACH(JAU_ENUM_CASE_LONG, type, __VA_ARGS__) \
653 default: \
654 return "undef " #stype; \
655 } \
656 } \
657 constexpr std::string_view \
658 name(const type v) noexcept \
659 { \
660 switch (v) { \
661 JAU_FOR_EACH(JAU_ENUM_CASE_SHORT, type, __VA_ARGS__) \
662 default: \
663 return "undef"; \
664 } \
665 } \
666 constexpr std::string_view \
667 type_name(const type) noexcept \
668 { \
669 return #stype; \
670 } \
671
672// static class member
673#define JAU_MAKE_ENUM_STRING_MEMBER(type, ...) \
674 JAU_MAKE_ENUM_STRING_SUB_MEMBER(type, type, __VA_ARGS__) \
675 \
676 constexpr static std::string \
677 to_string(const type e) noexcept \
678 { return std::string(name(e)); } \
679
680// static class member
681#define JAU_MAKE_BITFIELD_ENUM_STRING_MEMBER(type, ...) \
682 JAU_MAKE_ENUM_STRING_SUB_MEMBER(type, type, __VA_ARGS__) \
683 \
684 inline static std::string \
685 to_string(const type mask) noexcept { \
686 std::string out("["); \
687 bool comma = false; \
688 JAU_FOR_EACH_VALUE(JAU_APPEND_BITSTR, type, mask, __VA_ARGS__); \
689 out.append("]"); \
690 return out; \
691 } \
692
693// internal usage only (for static class member)
694#define JAU_MAKE_ENUM_STRING_SUB_MEMBER(type, stype, ...) \
695 constexpr static std::string_view \
696 long_name(const type v) noexcept \
697 { \
698 switch (v) { \
699 JAU_FOR_EACH(JAU_ENUM_CASE_LONG, type, __VA_ARGS__) \
700 default: \
701 return "undef " #stype; \
702 } \
703 } \
704 constexpr static std::string_view \
705 name(const type v) noexcept \
706 { \
707 switch (v) { \
708 JAU_FOR_EACH(JAU_ENUM_CASE_SHORT, type, __VA_ARGS__) \
709 default: \
710 return "undef"; \
711 } \
712 } \
713 constexpr static std::string_view \
714 type_name(const type) noexcept \
715 { \
716 return #stype; \
717 } \
718
719#define JAU_MAKE_ENUM_INFO(type, ...) \
720 JAU_MAKE_ENUM_INFO2(type, type, __VA_ARGS__) \
721
722#define JAU_MAKE_ENUM_INFO2(type, stype, ...) \
723 typedef jau::enums::enum_info<type, JAU_FOR_EACH_LIST(JAU_ENUM_TYPE_VALUE, type, __VA_ARGS__)> stype##_info_t; \
724
725
726/**@}*/
727
728#endif /* JAU_ENUM_UTIL_HPP_ */
Enumeration info template class including iterator (enum_iterator)
static constexpr size_type size() noexcept
number of all enum values
std::array< value_type, sizeof...(Vargs)> value_array_t
array type for all enum values (value_type), see size()
constexpr const_iterator cbegin() const noexcept
enum_iterator< value_type, Vargs... > const_iterator
enum_iterator to iterate over all enum values (const enum values)
constexpr iterator end() const noexcept
const value_type & reference
reference to value_type
const value_type * pointer
pointer to value_type
constexpr iterator begin() const noexcept
constexpr value_array_t values() const noexcept
constexpr enum_info(const enum_info &o) noexcept=delete
enum_iterator< value_type, Vargs... > iterator
enum_iterator to iterate over all enum values (const enum values)
constexpr std::string_view name() const noexcept
EnumType value_type
enum value type, i.e. the enum type itself
bool enum_info_tag
Used to determine whether this type is an enum_info, see is_enum_info<T>
constexpr const_iterator cend() const noexcept
static constexpr_cxx23 const enum_info & get() noexcept
Enumeration iterator, see enum_info.
constexpr bool operator==(const enum_iterator &rhs) const noexcept
Two way comparison operator, != is implicit, C++20.
constexpr enum_iterator operator--(int) noexcept
Post-decrement.
constexpr iterator_type base() const noexcept
Returns a copy of the underlying storage iterator.
constexpr enum_iterator operator++(int) noexcept
Post-increment.
constexpr bool is_begin() const noexcept
Returns true, if this iterator points to begin().
constexpr enum_iterator & operator--() noexcept
Pre-decrement; Well performing, return *this.
constexpr enum_iterator & operator++() noexcept
Pre-increment; Well performing, return *this.
constexpr value_type operator*() const noexcept
Dereferencing iterator to value_type reference.
constexpr enum_iterator & operator-=(difference_type i) noexcept
Subtraction-assignment of 'element_count'; Returns *this.
constexpr enum_iterator & to_end() noexcept
This iterator is set to the last element, end().
constexpr enum_iterator & operator=(enum_iterator &&o) noexcept=default
Assigns identity of given mutable iterator, if they are not identical.
constexpr difference_type dist_end() const noexcept
Returns the distance to_end() using zero as first index.
void swap(enum_iterator &o) noexcept
C++ named requirements: LegacyIterator: Swappable.
std::strong_ordering operator<=>(const enum_iterator &rhs) const noexcept
Three way std::strong_ordering comparison operator, C++20.
constexpr enum_iterator operator-(difference_type rhs) const noexcept
Binary 'iterator - element_count'.
const enum_info_t & description() const noexcept
constexpr value_type operator[](difference_type i) const noexcept
Subscript of 'element_index', returning immutable value_type.
constexpr bool is_end() const noexcept
Returns true, if this iterator points to end().
constexpr enum_iterator operator+(difference_type rhs) const noexcept
Binary 'iterator + element_count'.
constexpr difference_type dist_begin() const noexcept
Returns the distance to_begin() using zero as first index.
constexpr enum_iterator(const enum_iterator &o) noexcept=default
C++ named requirements: LegacyIterator: CopyConstructible.
constexpr difference_type operator-(const enum_iterator &rhs) const noexcept
Binary 'iterator - iterator -> element_count'; Returns element_count of type difference_type.
constexpr enum_iterator(enum_iterator &&o) noexcept=default
C++ named requirements: LegacyIterator: MoveConstructable.
constexpr const pointer operator->() const noexcept
Pointer to member access.
constexpr int compare(const enum_iterator &rhs) const noexcept
Returns signum or three-way comparison value.
enum_info< value_type, Vargs... > enum_info_t
constexpr enum_iterator & operator+=(difference_type i) noexcept
Addition-assignment of 'element_count'; Returns *this.
constexpr enum_iterator & operator=(const enum_iterator &o) noexcept=default
Assigns content of other mutable iterator to this one, if they are not identical.
constexpr enum_iterator & to_begin() noexcept
This iterator is set to the first element, begin().
consteval_cxx20 std::string_view name() noexcept
constexpr E & operator|=(E &lhs, const E rhs) noexcept
constexpr bool has_any(const E mask, const E bits) noexcept
constexpr std::underlying_type_t< E > number(const E v) noexcept
consteval_cxx20 NameTable< Vargs... > get_names() noexcept
constexpr std::underlying_type_t< E > operator*(const E v) noexcept
#define constexpr_cxx23
constexpr bool operator!=(const E lhs, const E rhs) noexcept
constexpr bool operator==(const E lhs, const E rhs) noexcept
constexpr ValueTable< std::common_type_t< Args... >, sizeof...(Args)> get_values(Args... args) noexcept
constexpr E & operator&=(E &lhs, const E rhs) noexcept
constexpr void append_bitstr(std::string &out, E mask, E bit, const std::string &bitstr, bool &comma)
constexpr bool is_set(const E mask, const E bits) noexcept
std::ostream & operator<<(std::ostream &os, const T v)
constexpr E & operator^=(E &lhs, const E rhs) noexcept
constexpr E operator^(const E lhs, const E rhs) noexcept
constexpr E operator|(const E lhs, const E rhs) noexcept
constexpr E operator&(const E lhs, const E rhs) noexcept
consteval_cxx20 bool is_enum() noexcept
Definition enum_util.hpp:84
consteval_cxx20 std::string_view long_name() noexcept
Definition enum_util.hpp:99
constexpr E & write(E &store, const E bits, bool set) noexcept
If set==true, sets the bits in store, i.e.
consteval_cxx20 const char * enum_funcname() noexcept
clang + gcc
Definition enum_util.hpp:77
constexpr E operator~(const E rhs) noexcept
#define consteval_cxx20
consteval qualifier replacement for C++20 consteval.
const char * type_name() noexcept
Returns the type name of given type T using template Compile Time Type Information (CTTI) only via RT...
Author: Sven Gothel sgothel@jausoft.com Copyright Gothel Software e.K.
Definition enum_util.hpp:65
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.
STL namespace.
std::string_view names[sizeof...(Vargs)]
template< class T > is_enum_info<T>::value compile-time Type Trait, determining whether the given tem...