jaulib v1.3.6
Jau Support Library (C++, Java, ..)
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 void append_bitstr(std::string& out, E mask, E bit, const std::string& bitstr, bool& comma) {
245 if( bit == (mask & bit) ) {
246 if( comma ) { out.append(", "); }
247 out.append(bitstr); comma = true;
248 }
249 }
250
251 template <typename T,
252 std::enable_if_t<std::is_enum_v<T>>* = nullptr>
253 inline std::ostream& operator<<(std::ostream& os, const T v) {
254 os << name(v);
255 return os;
256 }
257
258 template <typename EnumType, auto... Vargs> class enum_iterator; // fwd
259
260 /**
261 * Enumeration info template class including iterator (enum_iterator)
262 */
263 template <typename EnumType, auto... Vargs>
264 class enum_info {
265 public:
266 typedef size_t size_type;
267 typedef ssize_t difference_type;
268
269 /// enum value type, i.e. the enum type itself
270 typedef EnumType value_type;
271
272 /// pointer to value_type
273 typedef const value_type* pointer;
274 /// reference to value_type
275 typedef const value_type& reference;
276
277 /// enum_iterator to iterate over all enum values (const enum values)
279 /// enum_iterator to iterate over all enum values (const enum values)
281
282 /** Used to determine whether this type is an enum_info, see is_enum_info<T> */
283 typedef bool enum_info_tag;
284
285 /// array type for all enum values (value_type), see size()
286 typedef std::array<value_type, sizeof...(Vargs)> value_array_t;
287
288 /// number of all enum values
289 static constexpr size_type size() noexcept { return sizeof...(Vargs); }
290
291 private:
292 typedef const value_type* iterator_base_t;
293 value_array_t values_;
294 constexpr iterator_base_t begin_iter() const noexcept { return &values_[0]; }
295 constexpr iterator_base_t end_iter() const noexcept { return &values_[0] + size(); }
296 friend class enum_iterator<value_type, Vargs...>;
297
298 constexpr explicit enum_info() noexcept
299 : values_({{ Vargs... }})
300 { }
301
302 public:
303 constexpr enum_info(const enum_info& o) noexcept = delete;
304
305 constexpr_cxx23 static const enum_info& get() noexcept {
306 static enum_info singleton;
307 return singleton;
308 }
309
310 constexpr std::string_view name() const noexcept { return type_name(*begin()); }
311 constexpr value_array_t values() const noexcept { return values_; }
312
313 constexpr const_iterator cbegin() const noexcept { return const_iterator(*this, begin_iter()); }
314 constexpr const_iterator cend() const noexcept { return const_iterator(*this, end_iter()); }
315
316 constexpr iterator begin() const noexcept { return const_iterator(*this, begin_iter()); }
317 constexpr iterator end() const noexcept { return const_iterator(*this, end_iter()); }
318 };
319
320 /**
321 * <code>template< class T > is_enum_info<T>::value</code> compile-time Type Trait,
322 * determining whether the given template class is a enum_info type.
323 */
324 template< class, class = void >
325 struct is_enum_info : std::false_type { };
326
327 /**
328 * <code>template< class T > is_enum_info<T>::value</code> compile-time Type Trait,
329 * determining whether the given template class is a enum_info type.
330 */
331 template< class T >
332 struct is_enum_info<T, std::void_t<typename T::enum_info_tag>> : std::true_type { };
333
334 template <typename enum_info_t, std::enable_if_t<is_enum_info<enum_info_t>::value>* = nullptr>
335 inline std::ostream& operator<<(std::ostream& os, const enum_info_t& v) {
336 os << v.name() << "[";
337 typename enum_info_t::iterator end = v.end();
338 bool comma = false;
339 for(typename enum_info_t::iterator iter = v.begin(); iter != end; ++iter, comma=true) {
340 typename enum_info_t::value_type ev = *iter;
341 if( comma ) {
342 os << ", ";
343 }
344 os << ev << " (" << std::to_string( *ev ) << ")";
345 }
346 os << "]";
347 return os;
348 }
349
350 /**
351 * Enumeration iterator, see enum_info
352 */
353 template <typename EnumType, auto... Vargs>
354 class enum_iterator {
355 public:
356 typedef enum_info<EnumType, Vargs...> enum_info_t;
357
360
361 /// enum value type, i.e. the enum type itself
363
364 /// pointer to value_type
366
367 /// reference to value_type
369
370 /// enum_iterator to iterate over all enum values (const enum values)
371 typedef enum_info_t::iterator_base_t iterator_type;
372
373 private:
374 const enum_info_t& info_;
375 iterator_type iterator_;
376 friend class enum_info<EnumType, Vargs...>;
377
378 constexpr explicit enum_iterator(const enum_info_t& info, iterator_type iter) noexcept
379 : info_(info), iterator_(iter)
380 { }
381
382 public:
383 /**
384 * C++ named requirements: LegacyIterator: CopyConstructible
385 */
386 constexpr enum_iterator(const enum_iterator& o) noexcept = default;
387
388 /**
389 * Assigns content of other mutable iterator to this one,
390 * if they are not identical.
391 * <p>
392 * C++ named requirements: LegacyIterator: CopyAssignable
393 * </p>
394 * @param o the new identity value to be copied into this iterator
395 * @return reference to this
396 */
397 constexpr enum_iterator& operator=(const enum_iterator& o) noexcept = default;
398
399
400 /**
401 * C++ named requirements: LegacyIterator: MoveConstructable
402 */
403 constexpr enum_iterator(enum_iterator && o) noexcept = default;
404
405 /**
406 * Assigns identity of given mutable iterator,
407 * if they are not identical.
408 * <p>
409 * C++ named requirements: LegacyIterator: MoveAssignable
410 * </p>
411 * @param o the new identity to be taken
412 * @return reference to this
413 */
414 constexpr enum_iterator& operator=(enum_iterator&& o) noexcept = default;
415
416 const enum_info_t& description() const noexcept { return info_; }
417
418 /**
419 * C++ named requirements: LegacyIterator: Swappable
420 */
421 void swap(enum_iterator& o) noexcept {
422 std::swap( info_, o.info_);
423 std::swap( iterator_, o.iterator_);
424 }
425
426 /**
427 * Returns the distance to_end() using zero as first index. A.k.a the remaining elements iterable.
428 */
429 constexpr difference_type dist_end() const noexcept { return info_.end_iter() - iterator_; }
430
431 /**
432 * Returns true, if this iterator points to end().
433 */
434 constexpr bool is_end() const noexcept { return iterator_ == info_.end_iter(); }
435
436 /**
437 * This iterator is set to the last element, end(). Returns *this;
438 */
439 constexpr enum_iterator& to_end() noexcept
440 { iterator_ = info_.end_iter(); return *this; }
441
442 /**
443 * Returns the distance to_begin() using zero as first index. A.k.a the index from start.
444 */
445 constexpr difference_type dist_begin() const noexcept { return iterator_ - info_.begin_iter(); }
446
447 /**
448 * Returns true, if this iterator points to begin().
449 */
450 constexpr bool is_begin() const noexcept { return iterator_ == info_.begin_iter(); }
451
452 /**
453 * This iterator is set to the first element, begin(). Returns *this;
454 */
455 constexpr enum_iterator& to_begin() noexcept
456 { iterator_ = info_.begin_iter(); return *this; }
457
458 /**
459 * Returns a copy of the underlying storage iterator.
460 */
461 constexpr iterator_type base() const noexcept { return iterator_; }
462
463 // Multipass guarantee equality
464
465 /**
466 * Returns signum or three-way comparison value
467 * <pre>
468 * 0 if equal (both, store and iteratore),
469 * -1 if this->iterator_ < rhs_iter and
470 * 1 if this->iterator_ > rhs_iter (otherwise)
471 * </pre>
472 * @param rhs_store right-hand side store
473 * @param rhs_iter right-hand side iterator
474 */
475 constexpr int compare(const enum_iterator& rhs) const noexcept {
476 return iterator_ == rhs.iterator_ ? 0
477 : ( iterator_ < rhs.iterator_ ? -1 : 1);
478 }
479
480 /** Two way comparison operator, `!=` is implicit, C++20 */
481 constexpr bool operator==(const enum_iterator& rhs) const noexcept
482 { return iterator_ == rhs.iterator_; }
483
484 /** Three way std::strong_ordering comparison operator, C++20 */
485 std::strong_ordering operator<=>(const enum_iterator& rhs) const noexcept {
486 return iterator_ == rhs.iterator_ ? std::strong_ordering::equal :
487 ( iterator_ < rhs.iterator_ ? std::strong_ordering::less : std::strong_ordering::greater );
488 }
489
490 // Forward iterator requirements
491
492 /**
493 * Dereferencing iterator to value_type reference
494 * @return immutable reference to value_type
495 */
496 constexpr value_type operator*() const noexcept {
497 return *iterator_;
498 }
499
500 /**
501 * Pointer to member access.
502 * @return immutable pointer to value_type
503 */
504 constexpr const pointer operator->() const noexcept {
505 return &(*iterator_); // just in case iterator_type is a class, trick via dereference
506 }
507
508 /** Pre-increment; Well performing, return *this. */
509 constexpr enum_iterator& operator++() noexcept {
510 ++iterator_;
511 return *this;
512 }
513
514 /** Post-increment. */
515 constexpr enum_iterator operator++(int) noexcept
516 { return enum_iterator(info_, iterator_++); }
517
518 // Bidirectional iterator requirements
519
520 /** Pre-decrement; Well performing, return *this. */
521 constexpr enum_iterator& operator--() noexcept {
522 --iterator_;
523 return *this;
524 }
525
526 /** Post-decrement. */
527 constexpr enum_iterator operator--(int) noexcept
528 { return enum_iterator(info_, iterator_--); }
529
530 // Random access iterator requirements
531
532 /** Subscript of 'element_index', returning immutable value_type. */
533 constexpr value_type operator[](difference_type i) const noexcept
534 { return iterator_[i]; }
535
536 /** Addition-assignment of 'element_count'; Returns *this. */
537 constexpr enum_iterator& operator+=(difference_type i) noexcept
538 { iterator_ += i; return *this; }
539
540 /** Binary 'iterator + element_count' */
541 constexpr enum_iterator operator+(difference_type rhs) const noexcept
542 { return enum_iterator(info_, iterator_ + rhs); }
543
544 /** Subtraction-assignment of 'element_count'; Returns *this. */
545 constexpr enum_iterator& operator-=(difference_type i) noexcept
546 { iterator_ -= i; return *this; }
547
548 /** Binary 'iterator - element_count' */
549 constexpr enum_iterator operator-(difference_type rhs) const noexcept
550 { return enum_iterator(info_, iterator_ - rhs); }
551
552 // Distance or element count, binary subtraction of two iterator.
553
554 /** Binary 'iterator - iterator -> element_count'; Returns element_count of type difference_type. */
555 constexpr difference_type operator-(const enum_iterator& rhs) const noexcept
556 { return iterator_ - rhs.iterator_; }
557 };
558
559 /**@}*/
560
561} // namespace jau::enums
562
563/** \addtogroup CppLang
564 *
565 * @{
566 */
567
568//
569// JAU_FOR_EACH macros inspired by David Mazières, June 2021
570// <https://www.scs.stanford.edu/~dm/blog/va-opt.html>
571//
572// All hacks below to circumvent lack of C++26 reflection.
573//
574
575// Note space before (), so object-like macro
576#define JAU_PARENS ()
577
578#define JAU_EXPAND(...) JAU_EXPAND4(JAU_EXPAND4(JAU_EXPAND4(JAU_EXPAND4(__VA_ARGS__))))
579#define JAU_EXPAND4(...) JAU_EXPAND3(JAU_EXPAND3(JAU_EXPAND3(JAU_EXPAND3(__VA_ARGS__))))
580#define JAU_EXPAND3(...) JAU_EXPAND2(JAU_EXPAND2(JAU_EXPAND2(JAU_EXPAND2(__VA_ARGS__))))
581#define JAU_EXPAND2(...) JAU_EXPAND1(JAU_EXPAND1(JAU_EXPAND1(JAU_EXPAND1(__VA_ARGS__))))
582#define JAU_EXPAND1(...) __VA_ARGS__
583
584#define JAU_FOR_EACH(macro, type, ...) \
585 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH_HELPER(macro, type, __VA_ARGS__)))
586#define JAU_FOR_EACH_HELPER(macro, type, a1, ...) \
587 macro(type, a1) \
588 __VA_OPT__(JAU_FOR_EACH_AGAIN JAU_PARENS (macro, type, __VA_ARGS__))
589#define JAU_FOR_EACH_AGAIN() JAU_FOR_EACH_HELPER
590
591#define JAU_ENUM_CASE_SHORT(type, name) case type::name: return #name;
592#define JAU_ENUM_CASE_LONG(type, name) case type::name: return #type "::" #name;
593
594#define JAU_FOR_EACH_LIST(macro, type, ...) \
595 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH_LIST_HELPER(macro, type, __VA_ARGS__)))
596#define JAU_FOR_EACH_LIST_HELPER(macro, type, a1, ...) \
597 macro(type, a1) \
598 __VA_OPT__(, JAU_FOR_EACH_LIST_AGAIN JAU_PARENS (macro, type, __VA_ARGS__))
599#define JAU_FOR_EACH_LIST_AGAIN() JAU_FOR_EACH_LIST_HELPER
600
601#define JAU_ENUM_TYPE_VALUE(type, name) type::name
602#define JAU_ENUM_VALUE(type, name) name
603
604#define JAU_FOR_EACH_VALUE(macro, type, value, ...) \
605 __VA_OPT__(JAU_EXPAND(JAU_FOR_EACH_VALUE_HELPER(macro, type, value, __VA_ARGS__)))
606#define JAU_FOR_EACH_VALUE_HELPER(macro, type, value, a1, ...) \
607 macro(type, a1, value) \
608 __VA_OPT__(JAU_FOR_EACH_VALUE_AGAIN JAU_PARENS (macro, type, value, __VA_ARGS__))
609#define JAU_FOR_EACH_VALUE_AGAIN() JAU_FOR_EACH_VALUE_HELPER
610
611#define JAU_MAKE_ENUM_STRING(type, ...) \
612 JAU_MAKE_ENUM_STRING_SUB(type, type, __VA_ARGS__) \
613 \
614 constexpr std::string \
615 to_string(const type e) \
616 { return std::string(name(e)); } \
617
618#define JAU_APPEND_BITSTR(U,V,M) jau::enums::append_bitstr(out, M, U::V, #V, comma);
619
620#define JAU_MAKE_BITFIELD_ENUM_STRING(type, ...) \
621 JAU_MAKE_ENUM_STRING_SUB(type, type, __VA_ARGS__) \
622 \
623 inline std::string \
624 to_string(const type mask) { \
625 std::string out("["); \
626 bool comma = false; \
627 JAU_FOR_EACH_VALUE(JAU_APPEND_BITSTR, type, mask, __VA_ARGS__); \
628 out.append("]"); \
629 return out; \
630 } \
631
632#define JAU_MAKE_BITFIELD_ENUM_STRING2(type, stype, ...) \
633 JAU_MAKE_ENUM_STRING_SUB(type, stype, __VA_ARGS__) \
634 \
635 inline std::string \
636 to_string(const type mask) { \
637 std::string out("["); \
638 bool comma = false; \
639 JAU_FOR_EACH_VALUE(JAU_APPEND_BITSTR, type, mask, __VA_ARGS__); \
640 out.append("]"); \
641 return out; \
642 } \
643
644// internal usage only
645#define JAU_MAKE_ENUM_STRING_SUB(type, stype, ...) \
646 constexpr std::string_view \
647 long_name(const type v) noexcept \
648 { \
649 switch (v) { \
650 JAU_FOR_EACH(JAU_ENUM_CASE_LONG, type, __VA_ARGS__) \
651 default: \
652 return "undef " #stype; \
653 } \
654 } \
655 constexpr std::string_view \
656 name(const type v) noexcept \
657 { \
658 switch (v) { \
659 JAU_FOR_EACH(JAU_ENUM_CASE_SHORT, type, __VA_ARGS__) \
660 default: \
661 return "undef"; \
662 } \
663 } \
664 constexpr std::string_view \
665 type_name(const type) noexcept \
666 { \
667 return #stype; \
668 } \
669
670#define JAU_MAKE_ENUM_INFO(type, ...) \
671 JAU_MAKE_ENUM_INFO2(type, type, __VA_ARGS__) \
672
673#define JAU_MAKE_ENUM_INFO2(type, stype, ...) \
674 typedef jau::enums::enum_info<type, JAU_FOR_EACH_LIST(JAU_ENUM_TYPE_VALUE, type, __VA_ARGS__)> stype##_info_t; \
675
676
677/**@}*/
678
679#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...