enum_name
Loading...
Searching...
No Matches
mgutility_enum_name.hpp
1/*
2MIT License
3
4Copyright (c) 2024 mguludag
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
25#ifndef MGUTILITY_COMMON_DEFINITIONS_HPP
26#define MGUTILITY_COMMON_DEFINITIONS_HPP
27
38#ifdef _MSC_VER
39#ifndef MGUTILITY_CPLUSPLUS
40#define MGUTILITY_CPLUSPLUS _MSVC_LANG
41#endif
42#else
43#ifndef MGUTILITY_CPLUSPLUS
44#define MGUTILITY_CPLUSPLUS __cplusplus
45#endif
46#endif
47
55#if MGUTILITY_CPLUSPLUS == 201103L
56#define MGUTILITY_CNSTXPR
57#elif MGUTILITY_CPLUSPLUS > 201103L
58#define MGUTILITY_CNSTXPR constexpr
59#elif MGUTILITY_CPLUSPLUS < 201103L
60#error "Standards older than C++11 is not supported!"
61#endif
62
71#if (MGUTILITY_CPLUSPLUS >= 201703L && !defined(__clang__)) || \
72 (defined(__clang__) && __clang_major__ > 11 && \
73 MGUTILITY_CPLUSPLUS >= 201703L)
74#define MGUTILITY_CNSTXPR_CLANG_WA constexpr
75#else
76#define MGUTILITY_CNSTXPR_CLANG_WA
77#endif
78
85#if MGUTILITY_CPLUSPLUS > 201703L
86#define MGUTILITY_CNSTEVL consteval
87#else
88#define MGUTILITY_CNSTEVL
89#endif
90
97#if defined(__has_include) && !defined(MGUTILITY_HAS_HAS_INCLUDE)
98#define MGUTILITY_HAS_HAS_INCLUDE
99#endif
100
101#endif // MGUTILITY_COMMON_DEFINITIONS_HPP
102
103#ifndef DETAIL_META_HPP
104#define DETAIL_META_HPP
105
106#include <initializer_list>
107#include <type_traits>
108#include <utility>
109
110namespace mgutility {
111namespace detail {
112
113#ifndef MGUTILITY_ENUM_RANGE_MIN
119// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
120#define MGUTILITY_ENUM_RANGE_MIN 0
121#endif
122
123#ifndef MGUTILITY_ENUM_RANGE_MAX
129// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
130#define MGUTILITY_ENUM_RANGE_MAX 256
131#endif
132
138#ifndef MGUTILITY_ENUM_NAME_BUFFER_SIZE
139// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
140#define MGUTILITY_ENUM_NAME_BUFFER_SIZE 128U
141#endif
142
148template <typename E> struct is_scoped_enum {
152 static constexpr auto value =
153 // NOLINTNEXTLINE [modernize-type-traits]
154 std::is_enum<E>::value &&
155 // NOLINTNEXTLINE [modernize-type-traits]
156 !std::is_convertible<E, typename std::underlying_type<E>::type>::value;
157};
158
165template <typename T, typename = void> struct has_bit_or : std::false_type {};
166
173template <typename T>
174struct has_bit_or<T, decltype((T{} | T{}), void())> : std::true_type {};
175
176#if MGUTILITY_CPLUSPLUS > 201103L
182template <typename E>
183static constexpr bool is_scoped_enum_v = is_scoped_enum<E>::value;
184#endif
185
196template <bool B, class T = void>
197// NOLINTNEXTLINE [modernize-type-traits]
198using enable_if_t = typename std::enable_if<B, T>::type;
199
205template <typename T>
206// NOLINTNEXTLINE [modernize-type-traits]
207using underlying_type_t = typename std::underlying_type<T>::type;
208
214template <typename T>
215// NOLINTNEXTLINE [modernize-type-traits]
216using remove_const_t = typename std::remove_const<T>::type;
217
223template <std::size_t... Ints> struct index_sequence {};
224
231template <typename Seq1, typename Seq2> struct index_sequence_concat;
232
233template <std::size_t... I1, std::size_t... I2>
235 using type = index_sequence<I1..., (sizeof...(I1) + I2)...>;
236};
237
243template <std::size_t N> struct make_index_sequence_impl;
244
245template <std::size_t N> struct make_index_sequence_impl {
246private:
247 static constexpr std::size_t half = N / 2;
248
249 using first = typename make_index_sequence_impl<half>::type;
250 using second = typename make_index_sequence_impl<N - half>::type;
251
252public:
253 using type = typename index_sequence_concat<first, second>::type;
254};
255
256// base cases
260template <> struct make_index_sequence_impl<0> {
261 using type = index_sequence<>;
262};
263
267template <> struct make_index_sequence_impl<1> {
268 using type = index_sequence<0>;
269};
270
276template <std::size_t N>
277using make_index_sequence = typename make_index_sequence_impl<N>::type;
278
285template <typename Enum, Enum... Values> struct enum_sequence {};
286
294template <typename Enum, int Min, typename Seq> struct enum_sequence_from_index;
295
303template <typename Enum, int Min, std::size_t... I>
304struct enum_sequence_from_index<Enum, Min, index_sequence<I...>> {
305private:
306 // NOLINTNEXTLINE [readability-identifier-length]
307 static constexpr int offset(std::size_t i) {
308 return Min + static_cast<int>(i);
309 }
310
311public:
312 using type = enum_sequence<Enum, static_cast<Enum>(offset(I))...>;
313};
314
322template <typename Enum, int Min, int Max>
323using make_enum_sequence = typename enum_sequence_from_index<
324 Enum, Min,
325 make_index_sequence<static_cast<std::size_t>(Max - Min + 1)>>::type;
326} // namespace detail
327
333template <typename T> struct enum_range {
334 static constexpr auto min{MGUTILITY_ENUM_RANGE_MIN};
335 static constexpr auto max{MGUTILITY_ENUM_RANGE_MAX};
336};
337
338template <typename T, typename U> struct pair {
339 T first;
340 U second;
341};
342
343template <typename T>
344#if MGUTILITY_CPLUSPLUS >= 201402L || defined(__GNUC__) && !defined(__clang__)
345using flat_map = std::initializer_list<pair<T, const char *>>;
346#else
347// NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
348using flat_map = pair<T, const char *>[];
349#endif
350
356template <typename T> struct custom_enum {
357 // #if MGUTILITY_CPLUSPLUS > 201402L
358 static constexpr flat_map<T> map = {};
359 // #else
360 // static constexpr flat_map<T> map() noexcept {
361 // return {}; // default: empty map
362 // }
363 // #endif
364};
365
371template <typename T> struct enum_name_buffer {
372 static constexpr auto size = MGUTILITY_ENUM_NAME_BUFFER_SIZE;
373};
374
375} // namespace mgutility
376
377#endif // DETAIL_META_HPP
378
379#ifndef MGUTILITY_STRING_VIEW_HPP
380#define MGUTILITY_STRING_VIEW_HPP
381
382#include <cstring>
383// NOLINTNEXTLINE [unused-includes]
384#include <iosfwd>
385#include <string>
386#include <utility>
387
388#if MGUTILITY_CPLUSPLUS > 201402L
389#include <string_view>
390#endif
391
392namespace mgutility {
393namespace detail {
394
402// NOLINTNEXTLINE [readability-identifier-length]
403constexpr auto strlen_constexpr(const char *str, size_t sz = 0) noexcept
404 -> size_t {
405 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
406 return str[sz] == '\0' ? sz : strlen_constexpr(str, ++sz);
407}
408
415constexpr auto is_digit(char character) noexcept -> bool {
416 return character >= '0' && character <= '9';
417}
418
428MGUTILITY_CNSTXPR int strncmp_constexpr(const char *lhs, const char *rhs,
429 size_t count) noexcept {
430 for (size_t i = 0; i < count; ++i) {
431 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
432 if (lhs[i] != rhs[i] || lhs[i] == '\0' || rhs[i] == '\0') {
433 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
434 return static_cast<unsigned char>(lhs[i]) -
435 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
436 static_cast<unsigned char>(rhs[i]);
437 }
438 }
439 return 0;
440}
441
442template <typename Range, typename Pred>
443MGUTILITY_CNSTXPR auto find(const Range &rng, const Pred &pred) -> size_t {
444 for (size_t i = 1; i < rng.size(); ++i) {
445 if (pred == rng[i]) {
446 return i;
447 }
448 }
449 return 0;
450};
451
452} // namespace detail
453
454#if MGUTILITY_CPLUSPLUS < 201703L
455
461// NOLINTNEXTLINE [cppcoreguidelines-special-member-functions]
462template <typename Char = char> class basic_string_view {
463public:
467 // NOLINTNEXTLINE [readability-redundant-inline-specifier]
468 constexpr inline basic_string_view() noexcept : data_(""), size_(0) {}
469
475 // NOLINTNEXTLINE [google-explicit-constructor]
476 constexpr inline basic_string_view(const Char *str) noexcept
477 : data_(str), size_(detail::strlen_constexpr(str)) {}
478
484 // NOLINTNEXTLINE [google-explicit-constructor]
485 constexpr basic_string_view(const std::basic_string<Char> &str) noexcept
486 : data_(str.c_str()), size_(str.size()) {}
487
494 constexpr basic_string_view(const Char *str, size_t len) noexcept
495 : data_(str), size_(len) {}
496
502 constexpr basic_string_view(const basic_string_view &other)
503 : data_(other.data_), size_(other.size_) {}
504
510 constexpr basic_string_view(basic_string_view &&other) noexcept
511 : data_(std::move(other.data_)), size_(other.size_) {}
512
519 MGUTILITY_CNSTXPR inline basic_string_view<Char> &
520 operator=(const basic_string_view &other) noexcept = default;
521
528 MGUTILITY_CNSTXPR inline basic_string_view<Char> &
529 operator=(basic_string_view &&other) noexcept {
530 data_ = std::move(other.data_);
531 size_ = other.size_;
532 return *this;
533 }
534
541 // NOLINTNEXTLINE [readability-const-return-type]
542 constexpr const Char operator[](size_t index) const noexcept {
543 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
544 return data_[index];
545 }
546
552 constexpr const Char *begin() const noexcept { return data_; }
553
559 constexpr const Char *end() const noexcept { return (data_ + size_); }
560
566 constexpr bool empty() const noexcept { return size_ < 1; }
567
573 constexpr size_t size() const noexcept { return size_; }
574
580 constexpr const Char *data() const noexcept { return data_; }
581
590 size_t len = 0U) const noexcept {
591 return basic_string_view<Char>(data_ + begin,
592 len == 0U ? size_ - begin : len);
593 }
594
602 // NOLINTNEXTLINE [readability-identifier-length]
603 constexpr size_t rfind(Char c, size_t pos = npos) const noexcept {
604 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-pointer-arithmetic]
605 return (pos == npos ? pos = size_ : pos = pos),
606 c == data_[pos] ? pos
607 // NOLINTNEXTLINE [readability-avoid-nested-conditional-operator]
608 : pos == 0U ? npos
609 : rfind(c, --pos);
610 }
611
619 // NOLINTNEXTLINE [readability-identifier-length]
620 constexpr size_t find(Char c, size_t pos = 0) const noexcept {
621 // NOLINTNEXTLINE [readability-avoid-nested-conditional-operator]
622 return c == data_[pos] ? pos : pos < size_ ? find(c, ++pos) : npos;
623 }
624
632 MGUTILITY_CNSTXPR friend bool
634 basic_string_view<Char> rhs) noexcept {
635 return (lhs.size_ == rhs.size_) &&
636 detail::strncmp_constexpr(lhs.data_, rhs.data_, lhs.size_) == 0;
637 }
638
646 MGUTILITY_CNSTXPR friend bool operator==(basic_string_view<Char> lhs,
647 const Char *rhs) noexcept {
648 return ((lhs.size_ == detail::strlen_constexpr(rhs)) &&
649 (detail::strncmp_constexpr(lhs.data_, rhs, lhs.size_) == 0));
650 }
651
659 MGUTILITY_CNSTXPR friend bool
661 basic_string_view<Char> rhs) noexcept {
662 return !(lhs == rhs);
663 }
664
672 MGUTILITY_CNSTXPR friend bool operator!=(basic_string_view<Char> lhs,
673 const Char *rhs) noexcept {
674 return !(lhs == rhs);
675 }
676
682 // NOLINTNEXTLINE [google-explicit-constructor]
683 operator std::string() { return std::string(data_, size_); }
684
690 // NOLINTNEXTLINE [google-explicit-constructor]
691 operator std::string() const { return std::string(data_, size_); }
692
700 // NOLINTNEXTLINE [readability-identifier-length]
703 // NOLINTNEXTLINE [readability-identifier-length]
704 const basic_string_view<Char> &sv) {
705 // NOLINTNEXTLINE [readability-identifier-length]
706 for (auto c : sv) {
707 os << c;
708 }
709 return os;
710 }
711
712 static constexpr auto npos = -1;
713
714private:
715 size_t size_;
716 const Char *data_;
717};
718
719using string_view = basic_string_view<char>;
720
721#else
722
723using string_view = std::string_view;
724
725#endif
726
727} // namespace mgutility
728
729#endif // STRING_STRING_VIEW_HPP
730
731#ifndef MGUTILITY_FIXED_STRING_HPP
732#define MGUTILITY_FIXED_STRING_HPP
733
734namespace mgutility {
735
736template <size_t N = 0> class fixed_string {
737public:
738 template <size_t M>
739 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
740 MGUTILITY_CNSTXPR static auto make(const char (&str)[M]) -> fixed_string<M> {
741 return fixed_string<M>{str};
742 }
743
744 MGUTILITY_CNSTXPR fixed_string() = default;
745
746 // Constructor to initialize from a string literal
747 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
748 MGUTILITY_CNSTXPR explicit fixed_string(const char (&str)[N]) {
749 for (size_t i = 0; i < N - 1; ++i) {
750 data[i] = str[i];
751 }
752 cursor = N - 1;
753 data[cursor] = '\0';
754 }
755
756 // Concatenation operator
757 template <size_t M>
758 MGUTILITY_CNSTXPR auto operator+(const fixed_string<M> &other) const
759 -> fixed_string<N + M - 1> {
760 fixed_string<N + M - 1> result{};
761 size_t idx = 0;
762 for (; idx < N - 1; ++idx) {
763 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
764 result.data[idx] = data[idx];
765 }
766 for (size_t j = 0; j < M; ++j) {
767 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
768 result.data[idx + j] = other.data[j];
769 }
770 result.cursor = N + M - 2;
771 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
772 result.data[result.cursor] = '\0';
773 return result;
774 }
775
776 // Concatenation operator
777 template <size_t M>
778 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
779 MGUTILITY_CNSTXPR auto operator+(const char (&str)[M]) const
780 -> fixed_string<N + M - 1> {
781 return *this + fixed_string<M>{str};
782 }
783
784 template <size_t M>
785 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
786 MGUTILITY_CNSTXPR auto append(const char (&str)[M]) -> fixed_string<N> & {
787 static_assert(N > M,
788 "Capacity needs to be greater than string to be appended!");
789 for (size_t i = 0; i < M - 1; ++i) {
790 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
791 data[cursor++] = str[i];
792 }
793 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
794 data[cursor] = '\0';
795 return *this;
796 }
797
798 MGUTILITY_CNSTXPR auto append(string_view str) -> fixed_string<N> & {
799 for (const char chr : str) {
800 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
801 data[cursor++] = chr;
802 }
803 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
804 data[cursor] = '\0';
805 return *this;
806 }
807
808 MGUTILITY_CNSTXPR auto pop_back() -> void {
809 if (cursor > 0) {
810 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
811 data[--cursor] = '\0';
812 }
813 }
814
815 MGUTILITY_CNSTXPR auto size() const -> size_t { return cursor; }
816
817 // NOLINTNEXTLINE [readability-identifier-length]
818 constexpr size_t find(char c, size_t pos = 0) const noexcept {
819 // NOLINTNEXTLINE [readability-avoid-nested-conditional-operator]
820 return c == data[pos] ? pos : (pos < cursor ? find(c, ++pos) : npos);
821 }
822
823 // Conversion to std::string_view for easy printing
824 // NOLINTNEXTLINE[google-explicit-constructor]
825 MGUTILITY_CNSTXPR operator string_view() const {
826 return string_view(data, cursor);
827 }
828
829 MGUTILITY_CNSTXPR auto view() const -> string_view {
830 return string_view(data, cursor);
831 }
832
833 constexpr bool empty() const noexcept { return cursor == 0; }
834
835 constexpr const char &operator[](size_t index) const noexcept {
836 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
837 return data[index];
838 }
839
840 MGUTILITY_CNSTXPR inline bool operator==(const char *rhs) const {
841 return view() == rhs;
842 }
843
844 // NOLINTNEXTLINE [readability-identifier-length]
845 friend std::ostream &operator<<(std::ostream &os,
846 const fixed_string<N> &str) {
847 for (size_t i = 0; i < str.cursor; ++i) {
848 // NOLINTNEXTLINE [cppcoreguidelines-pro-bounds-constant-array-index]
849 os << str.data[i];
850 }
851 return os;
852 }
853
854 static constexpr auto npos = -1;
855
856private:
857 // NOLINTNEXTLINE [cppcoreguidelines-avoid-c-arrays]
858 char data[N]{'\0'};
859 size_t cursor{};
860};
861
862} // namespace mgutility
863
864#if defined(__cpp_lib_format)
865
866#include <format>
867
873template <size_t N>
874struct std::formatter<mgutility::fixed_string<N>>
875 : formatter<std::string_view> {
876 auto constexpr format(const mgutility::fixed_string<N> &str,
877 format_context &ctx) const {
878 return formatter<std::string_view>::format(str.view().data(), ctx);
879 }
880};
881
882#endif
883
884#if defined(ENUM_NAME_USE_FMT) || \
885 (defined(MGUTILITY_HAS_HAS_INCLUDE) && __has_include(<fmt/format.h>))
886#include <fmt/format.h>
887
888template <size_t N>
889struct fmt::formatter<mgutility::fixed_string<N>> : formatter<string_view> {
890 auto format(const mgutility::fixed_string<N> &str, format_context &ctx) const
891 -> appender {
892 return formatter<string_view>::format(str.view().data(), ctx);
893 }
894};
895#endif // MGUTILITY_USE_FMT || __has_include(<fmt/format.h>)
896
897#endif // MGUTILITY_FIXED_STRING_HPP
898
899#ifndef DETAIL_OPTIONAL_HPP
900#define DETAIL_OPTIONAL_HPP
901
902// NOLINTNEXTLINE [unused-includes]
903#include <exception>
904
905#if MGUTILITY_CPLUSPLUS >= 201703L
906#include <optional>
907#endif
908
909namespace mgutility {
910
911#if MGUTILITY_CPLUSPLUS < 201703L
912
916struct bad_optional_access : public std::exception {
922 const char *what() const noexcept override { return "optional has no value"; }
923};
924
925struct nullopt_t;
926
932template <typename T> class optional {
933public:
937 MGUTILITY_CNSTXPR inline explicit optional(nullopt_t & /*unused*/)
938 : dummy_{0}, has_value_{false} {}
939
943 MGUTILITY_CNSTXPR inline optional() : dummy_{0}, has_value_{false} {}
944
951 template <typename... Args>
952 MGUTILITY_CNSTXPR inline explicit optional(Args &&...args)
953 : value_{T{std::forward<Args>(args)...}}, has_value_{true} {}
954
960 MGUTILITY_CNSTXPR inline explicit optional(T &&value)
961 : value_{std::move(value)}, has_value_{true} {}
962
968 MGUTILITY_CNSTXPR inline optional(const optional &other)
969 : value_{other.value_}, has_value_{other.has_value_} {}
970
976 MGUTILITY_CNSTXPR inline optional(optional &&other) noexcept
977 : value_{other.value_}, has_value_{other.has_value_} {
978 other.reset();
979 }
980
984 ~optional() = default;
985
992 MGUTILITY_CNSTXPR inline optional &operator=(const optional &other) {
993 value_ = other.value_;
994 has_value_ = other.has_value_;
995 return *this;
996 }
997
1004 MGUTILITY_CNSTXPR inline optional &operator=(optional &&other) noexcept {
1005 value_ = other.value_;
1006 has_value_ = other.has_value_;
1007 other.reset();
1008 return *this;
1009 }
1010
1016 MGUTILITY_CNSTXPR inline void swap(optional &other) noexcept {
1017 auto val = std::move(other.value_);
1018 other.value_ = std::move(value_);
1019 value_ = std::move(val);
1020
1021 auto hval = other.has_value_;
1022 other.has_value_ = has_value_;
1023 has_value_ = hval;
1024 }
1025
1031 MGUTILITY_CNSTXPR inline T &operator*() { return value_; }
1032
1038 MGUTILITY_CNSTXPR inline T &operator*() const { return value_; }
1039
1046 MGUTILITY_CNSTXPR inline T &value() {
1047 if (!has_value_) {
1048 throw bad_optional_access();
1049 }
1050 return value_;
1051 }
1052
1059 MGUTILITY_CNSTXPR inline T &value() const {
1060 if (!has_value_) {
1061 throw bad_optional_access();
1062 }
1063 return value_;
1064 }
1065
1072 MGUTILITY_CNSTXPR inline T value_or(T &&value) {
1073 return has_value_ ? value_ : std::move(value);
1074 }
1075
1083 MGUTILITY_CNSTXPR inline T value_or(T &&value) const {
1084 return has_value_ ? value_ : std::move(value);
1085 }
1086
1093 MGUTILITY_CNSTXPR inline T value_or(const T &value) {
1094 return has_value_ ? value_ : value;
1095 }
1096
1104 MGUTILITY_CNSTXPR inline T value_or(const T &value) const {
1105 return has_value_ ? value_ : value;
1106 }
1107
1113 MGUTILITY_CNSTXPR inline void emplace(T value) {
1114 value_ = std::move(value);
1115 has_value_ = true;
1116 }
1117
1124 template <typename... Args>
1125 MGUTILITY_CNSTXPR inline void emplace(Args &&...args) {
1126 value_ = std::move(T{std::forward<Args>(args)...});
1127 has_value_ = true;
1128 }
1129
1135 MGUTILITY_CNSTXPR inline bool has_value() const { return has_value_; }
1136
1140 template <typename U = T,
1141 detail::enable_if_t<!std::is_destructible<U>::value, bool> = true>
1142 MGUTILITY_CNSTXPR inline void reset() {
1143 value_ = T{};
1144 has_value_ = false;
1145 }
1146
1150 template <typename U = T,
1151 detail::enable_if_t<std::is_destructible<T>::value, bool> = true>
1152 MGUTILITY_CNSTXPR inline void reset() {
1153 value_.~T();
1154 has_value_ = false;
1155 }
1156
1162 MGUTILITY_CNSTXPR operator bool() { return has_value_; }
1163
1164private:
1165 union {
1166 T value_;
1167 char dummy_[sizeof(T)];
1168 };
1169 bool has_value_;
1170};
1171
1182 template <typename T> MGUTILITY_CNSTXPR operator optional<T>() {
1183 return optional<T>{};
1184 }
1185};
1186
1191
1192#else
1198template <typename T> using optional = std::optional<T>;
1199
1203inline constexpr auto nullopt{std::nullopt};
1204
1205#endif
1206} // namespace mgutility
1207
1208#endif // DETAIL_OPTIONAL_HPP
1209
1210#ifndef DETAIL_ENUM_FOR_EACH_HPP
1211#define DETAIL_ENUM_FOR_EACH_HPP
1212
1213// NOLINTNEXTLINE [unused-includes]
1214#include <cstdint>
1215#include <utility>
1216
1217namespace mgutility {
1218namespace detail {
1228template <typename T>
1229// NOLINTNEXTLINE [modernize-type-traits]
1230using string_or_view_t = typename std::conditional<
1233
1240template <typename Enum>
1241using enum_pair = std::pair<Enum, detail::string_or_view_t<Enum>>;
1242} // namespace detail
1243
1249template <typename Enum> class enum_for_each {
1250 using value_type = const detail::enum_pair<Enum>;
1251 using size_type = std::size_t;
1252
1256 struct enum_iter {
1257 using const_iter_type = int;
1258 using iter_type = detail::remove_const_t<const_iter_type>;
1259 using iterator_category = std::forward_iterator_tag;
1260 using value_type = const detail::enum_pair<Enum>;
1261 using difference_type = std::ptrdiff_t;
1262 using pointer = value_type *;
1263 using reference = value_type &;
1264
1269 enum_iter() : m_pos{} {}
1270
1276 explicit enum_iter(iter_type value) : m_pos{value} {}
1277
1283 auto operator++() -> enum_iter & {
1284 ++m_pos;
1285 return *this;
1286 }
1287
1293 auto operator++(int) -> enum_iter {
1294 m_pos++;
1295 return *this;
1296 }
1297
1304 auto operator!=(const enum_iter &other) const -> bool {
1305 return m_pos != other.m_pos;
1306 }
1307
1314 auto operator==(const enum_iter &other) const -> bool {
1315 return m_pos == other.m_pos;
1316 }
1317
1323 auto operator*() const -> value_type;
1324
1325 private:
1326 iter_type m_pos;
1327 };
1328
1329public:
1333 enum_for_each() = default;
1334
1340 auto begin() -> enum_iter & { return m_begin; }
1341
1347 auto end() -> enum_iter & { return m_end; }
1348
1354 auto size() -> std::size_t {
1355 return static_cast<int>(enum_range<Enum>::max) -
1356 static_cast<int>(enum_range<Enum>::min) + 1;
1357 }
1358
1359private:
1360 enum_iter m_begin{
1361 static_cast<int>(enum_range<Enum>::min)};
1362 enum_iter m_end{static_cast<int>(enum_range<Enum>::max) +
1363 1};
1364};
1365} // namespace mgutility
1366
1367#endif // DETAIL_ENUM_FOR_EACH_HPP
1368
1369#ifndef MGUTILITY_REFLECTION_DETAIL_ENUM_NAME_IMPL_HPP
1370#define MGUTILITY_REFLECTION_DETAIL_ENUM_NAME_IMPL_HPP
1371
1372// NOLINTNEXTLINE [unused-includes]
1373#include <algorithm>
1374#include <array>
1375
1381#if defined(_MSC_VER) && _MSC_VER < 1910
1382#error "Requires MSVC 2017 or newer!"
1388#elif defined(__clang__) && __clang_major__ < 6
1389#error "Requires clang 6 or newer!"
1395#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 9
1396#error "Requires gcc 9 or newer!"
1402#elif !defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
1403#error "Your compiler is not supported!"
1404#endif
1405
1411#ifdef _MSC_VER
1412#define __PRETTY_FUNCTION__ __FUNCSIG__
1413#endif
1414
1415// NOLINTNEXTLINE [modernize-concat-nested-namespaces]
1416namespace mgutility {
1417namespace detail {
1418
1419#ifndef MGUTILITY_STRLEN
1420// NOLINTNEXTLINE [cppcoreguidelines-macro-usage]
1421#define MGUTILITY_STRLEN(x) sizeof(x) - 1
1422#endif
1423
1428struct enum_type {
1429private:
1437 template <typename Enum, Enum e>
1438 MGUTILITY_CNSTXPR static mgutility::string_view raw_name() noexcept {
1439#if defined(__GNUC__) && !defined(__clang__) && MGUTILITY_CPLUSPLUS >= 201402L
1440#define PREFIX \
1441 MGUTILITY_STRLEN("static constexpr mgutility::string_view " \
1442 "mgutility::detail::enum_type::raw_name()")
1443#elif defined(__clang__) || defined(__GNUC__)
1444#define PREFIX \
1445 MGUTILITY_STRLEN("static mgutility::string_view " \
1446 "mgutility::detail::enum_type::raw_name()")
1447#elif defined(_MSC_VER)
1448#if MGUTILITY_CPLUSPLUS > 201402L
1449#define PREFIX \
1450 MGUTILITY_STRLEN( \
1451 "class std::basic_string_view<char,struct std::char_traits<char> > " \
1452 "__cdecl mgutility::detail::enum_type::raw_name")
1453#else
1454#define PREFIX \
1455 MGUTILITY_STRLEN("class mgutility::basic_string_view<char> __cdecl " \
1456 "mgutility::detail::enum_type::raw_name")
1457#endif
1458#else
1459#define PREFIX 0
1460#endif
1461
1462 return mgutility::string_view(__PRETTY_FUNCTION__ + PREFIX,
1463 MGUTILITY_STRLEN(__PRETTY_FUNCTION__) -
1464 PREFIX + 1);
1465 }
1466
1473 MGUTILITY_CNSTXPR static mgutility::string_view
1474 parse(mgutility::string_view str) noexcept {
1475#if defined(__clang__) || defined(__GNUC__)
1476#if defined(__clang__)
1477 auto end = str.rfind(']');
1478#elif defined(__GNUC__) && !defined(__clang__)
1479 auto end = str.rfind(';');
1480#endif
1481 // Typical form:
1482 // "Enum = MyEnum::Value]"
1483
1484 auto pos = str.rfind('=', end);
1485 if (pos == mgutility::string_view::npos) {
1486 return {};
1487 }
1488 pos += 2; // skip "::"
1489
1490 auto result = str.substr(pos, end - pos);
1491
1492#elif defined(_MSC_VER)
1493 // MSVC: different format
1494 auto pos = str.rfind(',');
1495 if (pos == mgutility::string_view::npos)
1496 return {};
1497
1498 ++pos;
1499
1500 auto end = str.rfind('>');
1501 auto result = str.substr(pos, end - pos);
1502
1503#else
1504 return {};
1505#endif
1506
1507 if (result.empty()) {
1508 return {};
1509 }
1510
1511 // invalid cases look like "(Enum)123"
1512 if (result[0] == '(') {
1513 return {};
1514 }
1515
1516 return result.substr(result.rfind(':') + 1);
1517 }
1518
1519public:
1527 template <typename Enum, Enum e>
1528 MGUTILITY_CNSTXPR static mgutility::string_view name() noexcept {
1529 return parse(raw_name<Enum, e>());
1530 }
1531};
1532
1539template <typename Enum, typename Seq> struct enum_array_cache;
1540
1547template <typename Enum, Enum... Is>
1548struct enum_array_cache<Enum, detail::enum_sequence<Enum, Is...>> {
1549#if MGUTILITY_CPLUSPLUS >= 201402L
1550 // C++17+: fully constexpr
1551 // NOLINTNEXTLINE [readability-redundant-inline-specifier]
1552 static inline constexpr std::array<mgutility::string_view, sizeof...(Is) + 1>
1553 value() {
1554 std::array<mgutility::string_view, sizeof...(Is) + 1> arr{
1555 "", enum_type::template name<Enum, Is>()...};
1556
1557 constexpr auto map = mgutility::custom_enum<Enum>::map;
1558
1559 for (const auto &pair : map) {
1560 const int raw = static_cast<int>(pair.first);
1561 const auto idx =
1562 static_cast<size_t>(raw - mgutility::enum_range<Enum>::min + 1);
1563
1564 if (idx >= 1 && idx < arr.size()) {
1565 arr[idx] = pair.second;
1566 }
1567 }
1568
1569 return arr;
1570 }
1571#else
1572 // C++11: lazy runtime array
1573 static const std::array<mgutility::string_view, sizeof...(Is) + 1> &value() {
1574 static const std::array<mgutility::string_view, sizeof...(Is) + 1> arr =
1575 [] {
1576 std::array<mgutility::string_view, sizeof...(Is) + 1> tmp{
1577 "", enum_type::template name<Enum, Is>()...};
1578
1579 for (const auto &pair : mgutility::custom_enum<Enum>::map) {
1580 auto idx =
1581 static_cast<size_t>(static_cast<int>(pair.first) -
1583
1584 if (idx >= 1 && idx < tmp.size()) {
1585 tmp[idx] = pair.second;
1586 }
1587 }
1588
1589 return tmp;
1590 }();
1591
1592 return arr;
1593 }
1594#endif
1595};
1596
1605template <typename Enum, Enum... Is>
1606MGUTILITY_CNSTXPR auto
1607get_enum_array(detail::enum_sequence<Enum, Is...> /*unused*/) noexcept
1608#if MGUTILITY_CPLUSPLUS >= 201402L
1609 -> std::array<mgutility::string_view, sizeof...(Is) + 1> {
1610 return enum_array_cache<Enum, detail::enum_sequence<Enum, Is...>>::value();
1611#else
1612 -> const std::array<mgutility::string_view, sizeof...(Is) + 1> & {
1613 return enum_array_cache<Enum, detail::enum_sequence<Enum, Is...>>::value();
1614#endif
1615}
1616
1626template <typename Enum, int Min = mgutility::enum_range<Enum>::min,
1628MGUTILITY_CNSTXPR auto get_enum_array() noexcept
1629#if MGUTILITY_CPLUSPLUS >= 201402L
1630 -> std::array<mgutility::string_view, Max - Min + 2> {
1631 return get_enum_array<Enum>(detail::make_enum_sequence<Enum, Min, Max>());
1632#else
1633 -> const std::array<mgutility::string_view, Max - Min + 2> & {
1634 return get_enum_array<Enum>(detail::make_enum_sequence<Enum, Min, Max>());
1635#endif
1636}
1637
1647template <typename Enum, int Min, int Max>
1648MGUTILITY_CNSTXPR inline auto to_enum_impl(mgutility::string_view str) noexcept
1650 MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();
1651
1652 const auto index{detail::find(arr, str)};
1653 return index == 0
1655 : mgutility::optional<Enum>{static_cast<Enum>(index + Min - 1)};
1656}
1657
1667template <typename Enum, int Min, int Max>
1668MGUTILITY_CNSTXPR auto to_enum_bitmask_impl(mgutility::string_view str) noexcept
1670
1671 // Check if the string contains a '|' character
1672 if (str.find('|') == mgutility::string_view::npos) {
1673 return to_enum_impl<Enum, Min, Max>(str);
1674 }
1675
1677 std::size_t index = 0;
1678
1679 for (std::size_t i = 0; i < str.size(); ++i) {
1680 if (str[i] == '|') {
1681 auto name = str.substr(index, i - index);
1682 auto maybe_enum = to_enum_impl<Enum, Min, Max>(name);
1683
1684 if (!name.empty() && maybe_enum) {
1685 result.emplace(result ? static_cast<Enum>(*result | *maybe_enum)
1686 : *maybe_enum);
1687 }
1688
1689 index = i + 1;
1690 }
1691 }
1692
1693 auto maybe_enum = to_enum_impl<Enum, Min, Max>(str.substr(index));
1694 if (result && maybe_enum) {
1695 result.emplace(static_cast<Enum>(*result | *maybe_enum));
1696 } else {
1697 result.reset();
1698 }
1699
1700 return result;
1701}
1702
1712template <typename Enum, int Min, int Max,
1713 detail::enable_if_t<!detail::has_bit_or<Enum>::value, bool> = true>
1714MGUTILITY_CNSTXPR auto enum_name_impl(Enum enumValue) noexcept
1716 MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();
1717 const auto index{(Min < 0 ? -Min : Min) + static_cast<int>(enumValue) + 1};
1718 return arr[static_cast<size_t>(
1719 (index < Min || index > static_cast<int>(arr.size()) - 1) ? 0 : index)];
1720}
1721
1732// NOLINTNEXTLINE [modernize-use-constraints]
1733template <typename Enum, int Min, int Max,
1734 detail::enable_if_t<detail::has_bit_or<Enum>::value, bool> = true>
1735MGUTILITY_CNSTXPR_CLANG_WA auto enum_name_impl(Enum enumValue) noexcept
1737
1738 // Get the array of enum names
1739 MGUTILITY_CNSTXPR_CLANG_WA auto arr = get_enum_array<Enum, Min, Max>();
1740
1741 // Calculate the index in the array
1742 const auto index = (Min < 0 ? -Min : Min) + static_cast<int>(enumValue) + 1;
1743 const auto name =
1744 arr[(index < Min || index >= static_cast<int>(arr.size())) ? 0 : index];
1745
1746 // Return the name if it's valid
1747 if (!name.empty() && !is_digit(name[0])) {
1749 }
1750
1751 // Construct bitmasked name
1753 for (auto i = Min; i < Max; ++i) {
1754 const auto idx = (Min < 0 ? -Min : Min) + i + 1;
1755 if (idx >= 0 && idx < static_cast<int>(arr.size()) && !arr[idx].empty() &&
1756 !detail::is_digit(arr[idx][0]) &&
1757 (enumValue & static_cast<Enum>(i)) == static_cast<Enum>(i)) {
1758 bitmasked_name.append(arr[idx]).append("|");
1759 }
1760 }
1761
1762 // Remove the trailing '|' if present
1763 if (!bitmasked_name.empty()) {
1764 bitmasked_name.pop_back();
1765 }
1766
1767 return bitmasked_name;
1768}
1769} // namespace detail
1770} // namespace mgutility
1771
1772#endif // MGUTILITY_REFLECTION_DETAIL_ENUM_NAME_IMPL_HPP
1773
1774#ifndef MGUTILITY_ENUM_NAME_HPP
1775#define MGUTILITY_ENUM_NAME_HPP
1776
1777namespace mgutility {
1778
1786template <typename Enum,
1787 // NOLINTNEXTLINE [modernize-type-traits]
1788 detail::enable_if_t<std::is_enum<Enum>::value, bool> = true>
1789constexpr auto to_underlying(Enum enumValue) noexcept
1790 -> detail::underlying_type_t<Enum> {
1791 // NOLINTNEXTLINE [modernize-type-traits]
1792 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
1793 return static_cast<detail::underlying_type_t<Enum>>(enumValue);
1794}
1795
1805template <int Min, int Max, typename Enum>
1806MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept
1807 -> detail::string_or_view_t<Enum> {
1808 static_assert(Min < Max, "Max must be greater than Min!");
1809 // NOLINTNEXTLINE [modernize-type-traits]
1810 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
1811 return detail::enum_name_impl<Enum, Min, Max>(enumValue);
1812}
1813
1823template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
1824 int Max = static_cast<int>(enum_range<Enum>::max)>
1825MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept
1826 -> detail::string_or_view_t<Enum> {
1827 static_assert(Min < Max, "Max must be greater than Min!");
1828 // NOLINTNEXTLINE [modernize-type-traits]
1829 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
1830 return detail::enum_name_impl<Enum, Min, Max>(enumValue);
1831}
1832
1839template <typename Enum>
1840auto enum_for_each<Enum>::enum_iter::operator*() const -> value_type {
1841 auto value = static_cast<Enum>(m_pos);
1842 return detail::enum_pair<Enum>{value, enum_name(value)};
1843}
1844
1854template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
1855 int Max = static_cast<int>(enum_range<Enum>::max),
1856 detail::enable_if_t<!detail::has_bit_or<Enum>::value, bool> = true>
1857MGUTILITY_CNSTXPR auto to_enum(mgutility::string_view str) noexcept
1859 static_assert(Min < Max, "Max must be greater than Min!");
1860 // NOLINTNEXTLINE [modernize-type-traits]
1861 static_assert(std::is_enum<Enum>::value, "Type is not an Enum type!");
1862 return detail::to_enum_impl<Enum, Min, Max>(str);
1863}
1864
1874template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
1875 int Max = static_cast<int>(enum_range<Enum>::max),
1876 detail::enable_if_t<detail::has_bit_or<Enum>::value, bool> = true>
1877MGUTILITY_CNSTXPR auto to_enum(mgutility::string_view str) noexcept
1879 static_assert(Min < Max, "Max must be greater than Min!");
1880 // NOLINTNEXTLINE [modernize-type-traits]
1881 static_assert(std::is_enum<Enum>::value, "Type is not an Enum type!");
1882 return detail::to_enum_bitmask_impl<Enum, Min, Max>(str);
1883}
1884
1894template <typename Enum, int Min = static_cast<int>(enum_range<Enum>::min),
1895 int Max = static_cast<int>(enum_range<Enum>::max)>
1896MGUTILITY_CNSTXPR auto enum_cast(int value) noexcept
1898 static_assert(Min < Max, "Max must be greater than Min!");
1899 // NOLINTNEXTLINE [modernize-type-traits]
1900 static_assert(std::is_enum<Enum>::value, "Type is not an Enum type!");
1901 if (enum_name(static_cast<Enum>(value)).empty()) {
1902 return mgutility::nullopt;
1903 }
1904 return static_cast<Enum>(value);
1905}
1906
1907namespace operators {
1908template <typename Enum, mgutility::detail::enable_if_t<
1909 // NOLINTNEXTLINE [modernize-type-traits]
1910 std::is_enum<Enum>::value, bool> = true>
1911constexpr auto operator&(const Enum &lhs, const Enum &rhs) -> Enum {
1912 return static_cast<Enum>(mgutility::to_underlying(lhs) &
1914}
1915
1916template <typename Enum, mgutility::detail::enable_if_t<
1917 // NOLINTNEXTLINE [modernize-type-traits]
1918 std::is_enum<Enum>::value, bool> = true>
1919constexpr auto operator|(const Enum &lhs, const Enum &rhs) -> Enum {
1920 return static_cast<Enum>(mgutility::to_underlying(lhs) |
1922}
1923} // namespace operators
1924
1925} // namespace mgutility
1926
1935template <typename Enum, mgutility::detail::enable_if_t<
1936 // NOLINTNEXTLINE [modernize-type-traits]
1937 std::is_enum<Enum>::value, bool> = true>
1938auto operator<<(std::ostream &outStream, Enum enumVal) -> std::ostream & {
1939 // NOLINTNEXTLINE [modernize-type-traits]
1940 static_assert(std::is_enum<Enum>::value, "Value is not an Enum type!");
1941 outStream << mgutility::enum_name(enumVal);
1942 return outStream;
1943}
1944
1945#if defined(__cpp_lib_format)
1946
1947#include <format>
1948
1954template <typename Enum>
1955 requires std::is_enum_v<Enum>
1956struct std::formatter<Enum> : formatter<std::string_view> {
1957 // NOLINTNEXTLINE [readability-identifier-length]
1958 auto constexpr format(Enum e, format_context &ctx) const {
1959 return formatter<std::string_view>::format(mgutility::enum_name(e), ctx);
1960 }
1961};
1962
1963#endif
1964
1965#if defined(ENUM_NAME_USE_FMT) || \
1966 (defined(MGUTILITY_HAS_HAS_INCLUDE) && __has_include(<fmt/format.h>))
1967#include <fmt/format.h>
1968
1969template <class Enum>
1970struct fmt::formatter<Enum, char,
1971 // NOLINTNEXTLINE [modernize-type-traits]
1972 mgutility::detail::enable_if_t<std::is_enum<Enum>::value>>
1973 : formatter<string_view> {
1974 // NOLINTNEXTLINE [readability-identifier-length]
1975 auto format(const Enum e, format_context &ctx) const -> appender {
1976 return formatter<string_view>::format(
1977 static_cast<mgutility::string_view>(mgutility::enum_name(e)).data(),
1978 ctx);
1979 }
1980};
1981#endif // MGUTILITY_USE_FMT || __has_include(<fmt/format.h>)
1982
1983#endif // MGUTILITY_ENUM_NAME_HPP
A basic string view class template.
Definition mgutility_enum_name.hpp:462
constexpr basic_string_view(const Char *str) noexcept
Constructs a basic_string_view from a C-string.
Definition mgutility_enum_name.hpp:476
constexpr const Char * end() const noexcept
Returns an iterator to the end of the string.
Definition mgutility_enum_name.hpp:559
MGUTILITY_CNSTXPR basic_string_view< Char > & operator=(const basic_string_view &other) noexcept=default
Copy assignment operator.
constexpr basic_string_view(const basic_string_view &other)
Copy constructor.
Definition mgutility_enum_name.hpp:502
constexpr size_t size() const noexcept
Returns the size of the string.
Definition mgutility_enum_name.hpp:573
MGUTILITY_CNSTXPR friend bool operator==(basic_string_view< Char > lhs, const Char *rhs) noexcept
Equality operator.
Definition mgutility_enum_name.hpp:646
constexpr bool empty() const noexcept
Checks if the string is empty.
Definition mgutility_enum_name.hpp:566
friend std::ostream & operator<<(std::ostream &os, const basic_string_view< Char > &sv)
Stream insertion operator.
Definition mgutility_enum_name.hpp:702
constexpr basic_string_view(basic_string_view &&other) noexcept
Move constructor.
Definition mgutility_enum_name.hpp:510
MGUTILITY_CNSTXPR friend bool operator!=(basic_string_view< Char > lhs, const Char *rhs) noexcept
Inequality operator.
Definition mgutility_enum_name.hpp:672
constexpr size_t find(Char c, size_t pos=0) const noexcept
Finds the first occurrence of a character.
Definition mgutility_enum_name.hpp:620
constexpr const Char operator[](size_t index) const noexcept
Accesses the character at the given index.
Definition mgutility_enum_name.hpp:542
constexpr const Char * begin() const noexcept
Returns an iterator to the beginning of the string.
Definition mgutility_enum_name.hpp:552
constexpr basic_string_view() noexcept
Default constructor.
Definition mgutility_enum_name.hpp:468
constexpr size_t rfind(Char c, size_t pos=npos) const noexcept
Finds the last occurrence of a character.
Definition mgutility_enum_name.hpp:603
constexpr const Char * data() const noexcept
Returns a pointer to the underlying data.
Definition mgutility_enum_name.hpp:580
constexpr basic_string_view(const std::basic_string< Char > &str) noexcept
Constructs a basic_string_view from a std::string.
Definition mgutility_enum_name.hpp:485
constexpr basic_string_view(const Char *str, size_t len) noexcept
Constructs a basic_string_view from a C-string and length.
Definition mgutility_enum_name.hpp:494
MGUTILITY_CNSTXPR friend bool operator!=(basic_string_view< Char > lhs, basic_string_view< Char > rhs) noexcept
Inequality operator.
Definition mgutility_enum_name.hpp:660
MGUTILITY_CNSTXPR basic_string_view< Char > & operator=(basic_string_view &&other) noexcept
Move assignment operator.
Definition mgutility_enum_name.hpp:529
MGUTILITY_CNSTXPR friend bool operator==(basic_string_view< Char > lhs, basic_string_view< Char > rhs) noexcept
Equality operator.
Definition mgutility_enum_name.hpp:633
constexpr basic_string_view< Char > substr(size_t begin, size_t len=0U) const noexcept
Returns a substring view.
Definition mgutility_enum_name.hpp:589
A class template for iterating over enum values.
Definition enum_for_each.hpp:68
auto size() -> std::size_t
Returns the size of the enum range.
Definition mgutility_enum_name.hpp:1354
auto begin() -> enum_iter &
Returns an iterator to the beginning of the enum range.
Definition enum_for_each.hpp:159
auto end() -> enum_iter &
Returns an iterator to the end of the enum range.
Definition mgutility_enum_name.hpp:1347
Definition mgutility_enum_name.hpp:736
A class template that provides optional (nullable) objects.
Definition mgutility_enum_name.hpp:932
MGUTILITY_CNSTXPR T value_or(T &&value) const
Returns the stored value or a default value if empty (const version).
Definition mgutility_enum_name.hpp:1083
MGUTILITY_CNSTXPR void emplace(Args &&...args)
Constructs the value in-place with arguments.
Definition mgutility_enum_name.hpp:1125
MGUTILITY_CNSTXPR optional(Args &&...args)
Constructs an optional with a value.
Definition mgutility_enum_name.hpp:952
MGUTILITY_CNSTXPR optional & operator=(const optional &other)
Copy assignment operator.
Definition mgutility_enum_name.hpp:992
MGUTILITY_CNSTXPR optional & operator=(optional &&other) noexcept
Move assignment operator.
Definition mgutility_enum_name.hpp:1004
MGUTILITY_CNSTXPR optional(T &&value)
Constructs an optional with a value.
Definition mgutility_enum_name.hpp:960
MGUTILITY_CNSTXPR bool has_value() const
Checks if the optional has a value.
Definition mgutility_enum_name.hpp:1135
MGUTILITY_CNSTXPR T & operator*() const
Dereferences the stored value (const version).
Definition mgutility_enum_name.hpp:1038
MGUTILITY_CNSTXPR void swap(optional &other) noexcept
Swaps the contents of this optional with another.
Definition mgutility_enum_name.hpp:1016
MGUTILITY_CNSTXPR optional()
Constructs an empty optional.
Definition mgutility_enum_name.hpp:943
MGUTILITY_CNSTXPR T & operator*()
Dereferences the stored value.
Definition mgutility_enum_name.hpp:1031
MGUTILITY_CNSTXPR optional(const optional &other)
Copy constructor.
Definition mgutility_enum_name.hpp:968
MGUTILITY_CNSTXPR void reset()
Resets the optional, making it empty.
Definition mgutility_enum_name.hpp:1142
MGUTILITY_CNSTXPR optional(optional &&other) noexcept
Move constructor.
Definition mgutility_enum_name.hpp:976
~optional()=default
Destructor.
MGUTILITY_CNSTXPR optional(nullopt_t &)
Constructs an empty optional.
Definition mgutility_enum_name.hpp:937
MGUTILITY_CNSTXPR void emplace(T value)
Constructs the value in-place.
Definition mgutility_enum_name.hpp:1113
MGUTILITY_CNSTXPR T & value() const
Accesses the stored value (const version).
Definition mgutility_enum_name.hpp:1059
MGUTILITY_CNSTXPR T & value()
Accesses the stored value.
Definition mgutility_enum_name.hpp:1046
MGUTILITY_CNSTXPR T value_or(T &&value)
Returns the stored value or a default value if empty.
Definition mgutility_enum_name.hpp:1072
MGUTILITY_CNSTXPR T value_or(const T &value) const
Returns the stored value or a default value if empty (const version).
Definition mgutility_enum_name.hpp:1104
MGUTILITY_CNSTXPR T value_or(const T &value)
Returns the stored value or a default value if empty.
Definition mgutility_enum_name.hpp:1093
Definition doctest.h:530
Checks for MSVC compiler version.
Definition enum_for_each.hpp:35
auto nullopt
A global instance of nullopt_t to represent null optional.
Definition mgutility_enum_name.hpp:1190
MGUTILITY_CNSTXPR auto to_enum(mgutility::string_view str) noexcept -> mgutility::optional< Enum >
Converts a string to an enum value.
Definition enum_name.hpp:110
MGUTILITY_CNSTXPR auto enum_cast(int value) noexcept -> mgutility::optional< Enum >
Casts an integer value to an enum value.
Definition enum_name.hpp:149
MGUTILITY_CNSTXPR auto enum_name(Enum enumValue) noexcept -> detail::string_or_view_t< Enum >
Gets the name of an enum value.
Definition enum_name.hpp:59
constexpr auto to_underlying(Enum enumValue) noexcept -> detail::underlying_type_t< Enum >
Converts an enum value to its underlying integer value.
Definition enum_name.hpp:42
Exception thrown when accessing an empty optional.
Definition mgutility_enum_name.hpp:916
const char * what() const noexcept override
Returns the exception message.
Definition mgutility_enum_name.hpp:922
Provides the custom names map for an enumeration type.
Definition meta.hpp:227
Caches an array of enum names for a given enum sequence.
Definition enum_name_impl.hpp:260
Represents a sequence of enumeration values.
Definition meta.hpp:156
static MGUTILITY_CNSTXPR mgutility::string_view name() noexcept
Gets the name of the enum value, checking custom names first.
Definition mgutility_enum_name.hpp:1528
Concatenates two index sequences.
Definition mgutility_enum_name.hpp:231
Represents a compile-time sequence of indices.
Definition mgutility_enum_name.hpp:223
static constexpr auto value
Boolean value indicating if the type is a scoped enumeration.
Definition meta.hpp:84
Implementation helper for creating index sequences.
Definition mgutility_enum_name.hpp:245
Provides the range for an enumeration type.
Definition meta.hpp:204
Represents a null optional.
Definition mgutility_enum_name.hpp:1175
Definition meta.hpp:209