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