+
+
+
+
+
+
+
+ ![Logo]($relpath^$projectlogo) |
+
+
+
+ $projectname
+
+
+
+ $projectbrief
+ |
+
+
+
+
+ $projectbrief
+ |
+
+
+
+
+
+ $searchbox |
+
+
+
+
+
+
+
+ $searchbox |
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/doc/main.md.in b/doc/main.md.in
new file mode 100644
index 0000000..8b5b604
--- /dev/null
+++ b/doc/main.md.in
@@ -0,0 +1,5 @@
+# Main page
+
+Converting (scoped)enum values to string names written in C++>=11
+
+Version: @PROJECT_VERSION@
\ No newline at end of file
diff --git a/doc/version_selector_handler.js b/doc/version_selector_handler.js
new file mode 100644
index 0000000..7f0d1fc
--- /dev/null
+++ b/doc/version_selector_handler.js
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2024, Oleksandr Koval
+
+$(function () {
+ var repoName = window.location.pathname.split('/')[1];
+ $.get('/' + repoName + '/version_selector.html', function (data) {
+ // Inject version selector HTML into the page
+ $('#projectnumber').html(data);
+
+ // Event listener to handle version selection
+ document.getElementById('versionSelector').addEventListener('change', function () {
+ var selectedVersion = this.value;
+ window.location.href = '/' + repoName + '/' + selectedVersion + '/index.html';
+ });
+
+ // Set the selected option based on the current version
+ var currentVersion = window.location.pathname.split('/')[2];
+ $('#versionSelector').val(currentVersion);
+ });
+});
\ No newline at end of file
diff --git a/example/main.cpp b/example/main.cpp
index 4f0b051..65f7345 100644
--- a/example/main.cpp
+++ b/example/main.cpp
@@ -1,33 +1,80 @@
+#include "mgutility/reflection/enum_name.hpp"
#include
-#include "enum_name.hpp"
+enum class rgb_color {
+ red = 1 << 0,
+ green = 1 << 1,
+ blue = 1 << 2,
+ unknown = -1
+};
-enum class rgb_color { red, green, blue, unknown = -1};
+auto constexpr operator|(rgb_color lhs, rgb_color rhs) -> rgb_color {
+ return static_cast(mgutility::enum_to_underlying(lhs) |
+ mgutility::enum_to_underlying(rhs));
+}
+
+auto constexpr operator&(rgb_color lhs, rgb_color rhs) -> rgb_color {
+ return static_cast(mgutility::enum_to_underlying(lhs) &
+ mgutility::enum_to_underlying(rhs));
+}
-// you can specialize enum ranges with specialize struct per enum types (option 1)
-namespace mgutility{
- template<>
- struct enum_range
- {
- static constexpr auto min = -1;
- static constexpr auto max = 3;
- };
+// specialize rgb_color::unknown to make output "UNKNOWN" instead of "unknown"
+template <>
+constexpr auto
+mgutility::detail::enum_type::name() noexcept
+ -> mgutility::string_view {
+ return "UNKNOWN";
}
+// you can specialize enum ranges with overload per enum types (option 1)
+template <> struct mgutility::enum_range {
+ static constexpr auto min = -1;
+ static constexpr auto max = 5;
+};
+
// you can specialize enum ranges with overload per enum types (option 2)
-auto enum_name = [](rgb_color c){ return mgutility::enum_name<-1, 3>(c); };
-
-
-int main()
-{
- auto x = rgb_color::blue;
- auto y = mgutility::to_enum("green");
-
- // default signature: enum_name(Enum&&)
- // Changing max_value to not too much greater than enum's max value, it will compiles faster
- std::cout << mgutility::enum_name(x) << '\n'; // will print "blue" to output
-
- // calling specialized enum ranges function for rgb_color type
- // will print "green" to output, if y can't convert to rgb_color prints "unknown"
- std::cout << enum_name(y.value_or(rgb_color::unknown)) << '\n';
+auto enum_name = [](rgb_color c) { return mgutility::enum_name<-1, 5>(c); };
+
+#if defined(__cpp_lib_print)
+#include
+#include
+#endif
+
+int main() {
+ auto x = rgb_color::blue;
+ auto y = mgutility::to_enum("green|red");
+
+#if defined(__cpp_lib_print)
+
+ // enum_for_each can usable with views and range algorithms
+ auto colors = mgutility::enum_for_each() |
+ std::ranges::views::filter([](auto &&pair) {
+ return !pair.second.empty() && pair.second != "UNKNOWN";
+ });
+
+ std::ranges::for_each(colors, [](auto &&color) {
+ std::println("{} \t: {}", color.second,
+ mgutility::enum_to_underlying(color.first));
+ });
+
+#else
+
+ for (auto &&e : mgutility::enum_for_each()) {
+ if (!e.second.empty() && e.second != "UNKNOWN") {
+ std::cout << e.second << " \t: " << mgutility::enum_to_underlying(e.first)
+ << '\n';
+ }
+ // std::pair {enum_type, name_of_enum}
+ }
+#endif
+
+ // default signature: enum_name(Enum&&) Changing max_value to not too much greater than enum's
+ // max value, it will compiles faster
+ std::cout << x << '\n'; // will print "blue" to output
+
+ // calling specialized enum ranges function for rgb_color type
+ // will print "green" to output, if y can't convert to rgb_color prints
+ // "UNKNOWN"
+ std::cout << enum_name(y.value_or(rgb_color::unknown)) << '\n';
}
\ No newline at end of file
diff --git a/include/enum_name.hpp b/include/enum_name.hpp
deleted file mode 100644
index c7ed6ab..0000000
--- a/include/enum_name.hpp
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2023 Muhammed Galib Uludag
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef MGUTILITY_ENUM_NAME_HPP
-#define MGUTILITY_ENUM_NAME_HPP
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#if defined(_MSC_VER) && _MSC_VER < 1910
-#error "Requires MSVC 2017 or newer!"
-#elif defined(__clang__) && __clang_major__ < 6
-#error "Requires clang 6 or newer!"
-#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 9
-#error "Requires gcc 9 or newer!"
-#elif !defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
-#error "Your compiler is not supported!"
-#endif
-
-#ifdef _MSC_VER
-#define MG_ENUM_NAME_CPLUSPLUS _MSVC_LANG
-#else
-#define MG_ENUM_NAME_CPLUSPLUS __cplusplus
-#endif
-
-#if MG_ENUM_NAME_CPLUSPLUS == 201103L
-#define MG_ENUM_NAME_CNSTXPR
-#elif MG_ENUM_NAME_CPLUSPLUS > 201103L
-#define MG_ENUM_NAME_CNSTXPR constexpr
-#elif MG_ENUM_NAME_CPLUSPLUS < 201103L
-#error "Standards older than C++11 is not supported!"
-#endif
-
-#if MG_ENUM_NAME_CPLUSPLUS > 201702L
-#include
-#endif
-
-namespace mgutility {
-namespace detail {
-
-template
-struct is_scoped_enum {
- static constexpr auto value =
- std::is_enum::value &&
- !std::is_convertible::type>::value;
-};
-#if MG_ENUM_NAME_CPLUSPLUS > 201103L
-template
-static constexpr bool is_scoped_enum_v = is_scoped_enum::value;
-#endif
-
-template
-using underlying_type_t = typename std::underlying_type::type;
-
-template
-using remove_const_t = typename std::remove_const::type;
-
-#if MG_ENUM_NAME_CPLUSPLUS < 201703L
-
-template
-using enable_if_t = typename std::enable_if::type;
-
-constexpr auto strlen_constexpr(const char* str,
- size_t sz = 0) noexcept -> size_t {
- return str[sz] == '\0' ? sz : strlen_constexpr(str, ++sz);
-}
-
-template
-class basic_string_view {
- public:
- constexpr inline basic_string_view() noexcept : data_(""), size_(0) {}
- constexpr inline basic_string_view(const Char* str) noexcept
- : data_(str), size_(strlen_constexpr(str)) {}
- constexpr inline basic_string_view(const Char* str, size_t len) noexcept
- : data_(str), size_(len) {}
- constexpr inline basic_string_view(const basic_string_view& other)
- : data_(other.data_), size_(other.size_) {}
- constexpr inline basic_string_view(basic_string_view&& other) noexcept
- : data_(std::move(other.data_)), size_(std::move(other.size_)) {}
- MG_ENUM_NAME_CNSTXPR inline basic_string_view& operator=(
- const basic_string_view& other) noexcept {
- data_ = other.data_;
- size_ = other.size_;
- return *this;
- }
- MG_ENUM_NAME_CNSTXPR inline basic_string_view& operator=(
- basic_string_view&& other) noexcept {
- data_ = std::move(other.data_);
- size_ = std::move(other.size_);
- return *this;
- }
- constexpr inline const Char operator[](size_t index) const noexcept {
- return data_[index];
- }
- constexpr inline const Char* begin() const noexcept { return data_; }
- constexpr inline const Char* end() const noexcept {
- return (data_ + size_);
- }
- constexpr inline bool empty() const noexcept { return size_ < 1; }
- constexpr inline size_t size() const noexcept { return size_; }
- constexpr inline const Char* data() const noexcept { return data_; }
- constexpr inline basic_string_view substr(size_t begin,
- size_t len) const noexcept {
- return basic_string_view(data_ + begin, len);
- }
- constexpr inline size_t rfind(Char c, size_t pos = 0) const noexcept {
- return c == data_[pos] ? pos : rfind(c, --pos);
- }
-
- constexpr friend inline bool operator==(
- basic_string_view lhs, basic_string_view rhs) noexcept {
- return (lhs.size_ == rhs.size_) &&
- std::strncmp(lhs.data_, rhs.data_, lhs.size_) == 0;
- }
-
- constexpr friend inline bool operator==(basic_string_view lhs,
- const Char* rhs) noexcept {
- return (lhs.size_ == strlen_constexpr(rhs)) &&
- std::strncmp(lhs.data_, rhs, lhs.size_) == 0;
- }
-
- constexpr friend inline bool operator!=(
- basic_string_view lhs, basic_string_view rhs) noexcept {
- return !(lhs == rhs);
- }
-
- constexpr friend inline bool operator!=(basic_string_view lhs,
- const Char* rhs) noexcept {
- return !(lhs == rhs);
- }
-
- inline operator std::string() { return std::string(data_, size_); }
- inline operator std::string() const { return std::string(data_, size_); }
-
- friend inline std::ostream& operator<<(std::ostream& os,
- const basic_string_view& sv) {
- for (auto c : sv) {
- os << c;
- }
- return os;
- }
-
- private:
- size_t size_;
- const Char* data_;
-};
-
-using string_view = basic_string_view;
-
-struct bad_optional_access : public std::exception {
- const char* what() const noexcept { return "optional has no value"; }
-};
-
-struct nullopt_t;
-
-template
-class optional {
- public:
- MG_ENUM_NAME_CNSTXPR inline optional(nullopt_t&)
- : dummy_{0}, has_value_{false} {}
- MG_ENUM_NAME_CNSTXPR inline optional() : dummy_{0}, has_value_{false} {}
- template
- MG_ENUM_NAME_CNSTXPR inline optional(Args&&... args)
- : value_{T{std::forward(args)...}}, has_value_{true} {}
- MG_ENUM_NAME_CNSTXPR inline optional(T&& value)
- : value_{value}, has_value_{true} {}
- MG_ENUM_NAME_CNSTXPR inline optional(const optional& other)
- : value_{other.value_}, has_value_{other.has_value_} {}
- MG_ENUM_NAME_CNSTXPR inline optional(optional&& other)
- : value_{other.value_}, has_value_{other.has_value_} {
- other.reset();
- }
- inline ~optional() { has_value_ = false; }
- MG_ENUM_NAME_CNSTXPR inline optional& operator=(const optional& other) {
- value_ = other.value_;
- has_value_ = other.has_value_;
- return *this;
- }
- MG_ENUM_NAME_CNSTXPR inline optional& operator=(optional&& other) {
- value_ = other.value_;
- has_value_ = other.has_value_;
- other.reset();
- return *this;
- }
- MG_ENUM_NAME_CNSTXPR inline void swap(optional&& other) {
- auto val = std::move(other.value_);
- other.value_ = std::move(value_);
- value_ = std::move(val);
-
- auto hval = std::move(other.has_value_);
- other.has_value_ = std::move(has_value_);
- has_value_ = std::move(hval);
- }
- MG_ENUM_NAME_CNSTXPR inline T& operator*() { return value_; }
- MG_ENUM_NAME_CNSTXPR inline T& operator*() const { return value_; }
- MG_ENUM_NAME_CNSTXPR inline T& value() {
- if (!has_value_) throw detail::bad_optional_access();
- return value_;
- }
- MG_ENUM_NAME_CNSTXPR inline T& value() const {
- if (!has_value_) throw detail::bad_optional_access();
- return value_;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(T&& value) {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(T&& value) const {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(const T& value) {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(const T& value) const {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline void emplace(T value) {
- value_ = std::move(value);
- has_value_ = true;
- }
- template
- MG_ENUM_NAME_CNSTXPR inline void emplace(Args&&... args) {
- value_ = std::move(T{std::forward(args)...});
- has_value_ = true;
- }
- MG_ENUM_NAME_CNSTXPR inline bool has_value() const { return has_value_; }
-
-#if !(defined(__clang__) && __clang_major__ < 11)
- template ::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR inline void reset() {
- T::~T();
- has_value_ = false;
- }
-#endif
- template ::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR inline void reset() {
- value_ = T{};
- has_value_ = false;
- }
-
- MG_ENUM_NAME_CNSTXPR operator bool() { return has_value_; }
-
- private:
- union {
- T value_;
- char dummy_[sizeof(T)];
- };
- bool has_value_;
-};
-
-struct nullopt_t {
- template
- MG_ENUM_NAME_CNSTXPR operator optional() {
- return optional{};
- }
-};
-
-auto nullopt = nullopt_t{};
-
-#else
-
-template
-using optional = std::optional;
-inline constexpr auto nullopt{std::nullopt};
-using string_view = std::string_view;
-template
-using enable_if_t = std::enable_if_t;
-
-#endif
-
-template
-struct enum_sequence {};
-
-template
-struct enum_sequence_helper
- : enum_sequence_helper {};
-
-template
-struct enum_sequence_helper {
- using type = enum_sequence(Next)...>;
-};
-
-template
-using make_enum_sequence = typename enum_sequence_helper::type;
-
-struct enum_type {
-#if defined(_MSC_VER)
-#define __PRETTY_FUNCTION__ __FUNCSIG__
-#endif
- template <
- typename Enum, Enum e,
- detail::enable_if_t::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR static inline auto name() noexcept
- -> detail::string_view {
- auto str = detail::string_view(__PRETTY_FUNCTION__);
- auto offset{lastidxenumname[0] + lastidxenumname[1]};
- auto index =
- std::max(str.rfind(lastidxenumname[2], str.size() - offset),
- str.rfind(lastidxenumname[3], str.size() - offset));
- auto result = str.substr(index + 1, str.size() - offset - index);
- return result[0] == '(' ? "" : result;
- }
-
- template <
- typename Enum, Enum e,
- detail::enable_if_t::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR static inline auto name() noexcept
- -> detail::string_view {
- auto str = detail::string_view(__PRETTY_FUNCTION__);
- auto index =
- str.rfind(lastidxenumname[3], str.size() - lastidxenumname[0]) + 1;
- auto result =
- str.substr(index, str.size() - lastidxenumname[0] - index);
- return result.size() > 4 ? result[4] == lastidxenumname[4] ? "" : result
- : result;
- }
-
- private:
- static constexpr int lastidxenumname[] =
-#if defined(_MSC_VER)
- {22, 0, ',', ':', '<'};
-#elif defined(__clang__)
- {1, 1, ' ', ':', '('};
-#elif defined(__GNUC__)
- {
-#if MG_ENUM_NAME_CPLUSPLUS < 201703L
- 179,
-#else
- 165,
-#endif
- 5, ' ', ':', '('};
-#endif
-};
-
-template
-using enum_pair = std::pair;
-
-template
-inline auto get_enum_array(detail::enum_sequence) noexcept
- -> std::array {
- static std::array
- arr{"", enum_type::template name()...};
- return arr;
-}
-
-template
-inline auto to_enum_impl(detail::string_view str) noexcept
- -> detail::optional {
- auto arr = get_enum_array(detail::make_enum_sequence());
- const auto index{std::find(arr.begin() + 1, arr.end(), str)};
- return index == arr.end()
- ? detail::nullopt
- : detail::optional{static_cast(
- std::distance(arr.begin(), index) + Min - 1)};
-}
-
-template
-inline auto enum_name_impl(Enum e) noexcept -> detail::string_view {
- auto arr = get_enum_array(detail::make_enum_sequence());
- const auto index{std::abs(Min) + static_cast(e) + (Min < 0 ? 1 : 1)};
- return arr[(index < Min || index > arr.size() - 1) ? 0 : index];
-}
-} // namespace detail
-} // namespace mgutility
-
-namespace mgutility {
-template
-struct enum_range {
- static constexpr auto min{-128};
- static constexpr auto max{128};
-};
-
-template
-class enum_for_each {
- using value_type = const detail::enum_pair;
- using size_type = std::size_t;
-
- struct enum_iter {
- using const_iter_type = decltype(enum_range::min);
- using iter_type = detail::remove_const_t;
- using iterator_category = std::forward_iterator_tag;
- using value_type = const detail::enum_pair;
- using difference_type = std::ptrdiff_t;
- using pointer = value_type*;
- using reference = value_type&;
-
- enum_iter() : m_pos{} {}
- enum_iter(iter_type value) : m_pos{value} {}
-
- auto operator++() -> enum_iter& {
- ++m_pos;
- return *this;
- }
-
- auto operator++(int) -> enum_iter {
- m_pos++;
- return *this;
- }
-
- auto operator!=(const enum_iter& other) const -> bool {
- return m_pos != other.m_pos;
- }
-
- auto operator==(const enum_iter& other) const -> bool {
- return m_pos == other.m_pos;
- }
-
- auto operator*() const -> value_type;
-
- private:
- iter_type m_pos;
- };
-
- public:
- enum_for_each() {}
- auto begin() -> enum_iter& { return m_begin; }
- auto end() -> enum_iter& { return m_end; }
- auto size() -> std::size_t {
- return enum_range::max - enum_range::min;
- }
-
- private:
- enum_iter m_begin{enum_range::min};
- enum_iter m_end{enum_range::max};
-};
-
-template
-constexpr inline auto enum_to_underlying(Enum e) noexcept
- -> detail::underlying_type_t {
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- return static_cast>(e);
-}
-
-template
-MG_ENUM_NAME_CNSTXPR inline auto enum_name(Enum e) noexcept
- -> detail::string_view {
- static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- return detail::enum_name_impl(e);
-}
-
-template ::min,
- int Max = enum_range::max>
-MG_ENUM_NAME_CNSTXPR inline auto enum_name(Enum e) noexcept
- -> detail::string_view {
- static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- return detail::enum_name_impl(e);
-}
-
-template
-auto enum_for_each::enum_iter::operator*() const -> value_type {
- auto value = static_cast(m_pos);
- return detail::enum_pair{value, enum_name(value)};
-}
-
-template ::min,
- int Max = enum_range::max>
-MG_ENUM_NAME_CNSTXPR inline auto to_enum(detail::string_view str) noexcept
- -> detail::optional {
- static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
- static_assert(std::is_enum::value, "Type is not an Enum type!");
- return detail::to_enum_impl(str);
-}
-} // namespace mgutility
-
-template ::value, bool>::type = true>
-auto operator<<(std::ostream& os, Enum e) -> std::ostream& {
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- os << mgutility::enum_name(e);
- return os;
-}
-
-#endif // MGUTILITY_ENUM_NAME_HPP
diff --git a/include/mgutility/_common/definitions.hpp b/include/mgutility/_common/definitions.hpp
new file mode 100644
index 0000000..8a5af59
--- /dev/null
+++ b/include/mgutility/_common/definitions.hpp
@@ -0,0 +1,84 @@
+/*
+MIT License
+
+Copyright (c) 2024 mguludag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+
+#ifndef MGUTILITY_COMMON_DEFINITIONS_HPP
+#define MGUTILITY_COMMON_DEFINITIONS_HPP
+
+/**
+ * @file definitions.hpp
+ * @brief Defines macros for compiler and standard support detection.
+ */
+
+/**
+ * @brief Defines the MGUTILITY_CPLUSPLUS macro for MSVC and other compilers.
+ *
+ * For MSVC, it uses _MSVC_LANG. For other compilers, it uses __cplusplus.
+ */
+#ifdef _MSC_VER
+#define MGUTILITY_CPLUSPLUS _MSVC_LANG
+#else
+#define MGUTILITY_CPLUSPLUS __cplusplus
+#endif
+
+/**
+ * @brief Defines the MGUTILITY_CNSTXPR macro based on the C++ standard.
+ *
+ * If the C++ standard is C++11, MGUTILITY_CNSTXPR is defined as empty.
+ * If the C++ standard is newer than C++11, MGUTILITY_CNSTXPR is defined as constexpr.
+ * If the C++ standard is older than C++11, an error is raised.
+ */
+#if MGUTILITY_CPLUSPLUS == 201103L
+#define MGUTILITY_CNSTXPR
+#elif MGUTILITY_CPLUSPLUS > 201103L
+#define MGUTILITY_CNSTXPR constexpr
+#elif MGUTILITY_CPLUSPLUS < 201103L
+#error "Standards older than C++11 is not supported!"
+#endif
+
+/**
+ * @brief Defines the MGUTILITY_CNSTXPR_CLANG_WA macro based on the C++ standard.
+ *
+ * If the C++ standard is newer than C++17 and the compiler is not Clang,
+ * MGUTILITY_CNSTXPR_CLANG_WA is defined as constexpr. Otherwise, it is defined as empty.
+ */
+#if MGUTILITY_CPLUSPLUS > 201703L
+#define MGUTILITY_CNSTXPR_CLANG_WA constexpr
+#else
+#define MGUTILITY_CNSTXPR_CLANG_WA
+#endif
+
+/**
+ * @brief Defines the MGUTILITY_CNSTEVL macro based on the C++ standard.
+ *
+ * If the C++ standard is newer than C++17, MGUTILITY_CNSTEVL is defined as consteval.
+ * Otherwise, it is defined as empty.
+ */
+#if MGUTILITY_CPLUSPLUS > 201703L
+#define MGUTILITY_CNSTEVL consteval
+#else
+#define MGUTILITY_CNSTEVL
+#endif
+
+#endif // MGUTILITY_COMMON_DEFINITIONS_HPP
diff --git a/include/mgutility/reflection/detail/enum_for_each.hpp b/include/mgutility/reflection/detail/enum_for_each.hpp
new file mode 100644
index 0000000..fcf983c
--- /dev/null
+++ b/include/mgutility/reflection/detail/enum_for_each.hpp
@@ -0,0 +1,190 @@
+/*
+MIT License
+
+Copyright (c) 2024 mguludag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef DETAIL_ENUM_FOR_EACH_HPP
+#define DETAIL_ENUM_FOR_EACH_HPP
+
+#include "meta.hpp"
+#include "mgutility/std/string_view.hpp"
+
+#include
+#include
+
+namespace mgutility
+{
+ namespace detail
+ {
+ /**
+ * @brief Alias template for a string or string view type based on the presence
+ * of a bitwise OR operator.
+ *
+ * If the type T supports the bitwise OR operator, the alias is a std::string.
+ * Otherwise, it is a mgutility::string_view.
+ *
+ * @tparam T The type to check.
+ */
+ template
+ using string_or_view_t =
+ typename std::conditional::value, std::string,
+ mgutility::string_view>::type;
+
+ /**
+ * @brief A pair consisting of an enum value and its corresponding string or
+ * string view.
+ *
+ * @tparam Enum The enum type.
+ */
+ template
+ using enum_pair = std::pair>;
+ } // namespace detail
+
+ /**
+ * @brief A class template for iterating over enum values.
+ *
+ * @tparam Enum The enum type.
+ */
+ template
+ class enum_for_each
+ {
+ using value_type = const detail::enum_pair;
+ using size_type = std::size_t;
+
+ /**
+ * @brief An iterator for enum values.
+ */
+ struct enum_iter
+ {
+ using const_iter_type = decltype(enum_range::min);
+ using iter_type = detail::remove_const_t;
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const detail::enum_pair;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type *;
+ using reference = value_type &;
+
+ /**
+ * @brief Default constructor initializing the iterator to the default
+ * position.
+ */
+ enum_iter() : m_pos{} {}
+
+ /**
+ * @brief Constructor initializing the iterator to a specific position.
+ *
+ * @param value The initial position of the iterator.
+ */
+ enum_iter(iter_type value) : m_pos{value} {}
+
+ /**
+ * @brief Pre-increment operator.
+ *
+ * @return A reference to the incremented iterator.
+ */
+ auto operator++() -> enum_iter &
+ {
+ ++m_pos;
+ return *this;
+ }
+
+ /**
+ * @brief Post-increment operator.
+ *
+ * @return A copy of the iterator before incrementing.
+ */
+ auto operator++(int) -> enum_iter
+ {
+ m_pos++;
+ return *this;
+ }
+
+ /**
+ * @brief Inequality comparison operator.
+ *
+ * @param other The other iterator to compare with.
+ * @return True if the iterators are not equal, otherwise false.
+ */
+ auto operator!=(const enum_iter &other) const -> bool
+ {
+ return m_pos != other.m_pos;
+ }
+
+ /**
+ * @brief Equality comparison operator.
+ *
+ * @param other The other iterator to compare with.
+ * @return True if the iterators are equal, otherwise false.
+ */
+ auto operator==(const enum_iter &other) const -> bool
+ {
+ return m_pos == other.m_pos;
+ }
+
+ /**
+ * @brief Dereference operator.
+ *
+ * @return The current enum pair.
+ */
+ auto operator*() const -> value_type;
+
+ private:
+ iter_type m_pos; /**< The current position of the iterator. */
+ };
+
+ public:
+ /**
+ * @brief Default constructor.
+ */
+ enum_for_each() = default;
+
+ /**
+ * @brief Returns an iterator to the beginning of the enum range.
+ *
+ * @return A reference to the beginning iterator.
+ */
+ auto begin() -> enum_iter & { return m_begin; }
+
+ /**
+ * @brief Returns an iterator to the end of the enum range.
+ *
+ * @return A reference to the end iterator.
+ */
+ auto end() -> enum_iter & { return m_end; }
+
+ /**
+ * @brief Returns the size of the enum range.
+ *
+ * @return The size of the enum range.
+ */
+ auto size() -> std::size_t
+ {
+ return enum_range::max - enum_range::min;
+ }
+
+ private:
+ enum_iter m_begin{enum_range::min}; /**< The beginning iterator. */
+ enum_iter m_end{enum_range::max}; /**< The end iterator. */
+ };
+} // namespace mgutility
+
+#endif // DETAIL_ENUM_FOR_EACH_HPP
\ No newline at end of file
diff --git a/include/mgutility/reflection/detail/enum_name_impl.hpp b/include/mgutility/reflection/detail/enum_name_impl.hpp
new file mode 100644
index 0000000..b091523
--- /dev/null
+++ b/include/mgutility/reflection/detail/enum_name_impl.hpp
@@ -0,0 +1,323 @@
+/*
+MIT License
+
+Copyright (c) 2024 mguludag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef DETAIL_ENUM_NAME_IMPL_HPP
+#define DETAIL_ENUM_NAME_IMPL_HPP
+
+#include "enum_for_each.hpp"
+#include "mgutility/std/optional.hpp"
+#include "mgutility/std/string_view.hpp"
+
+#include
+#include
+
+/**
+ * @brief Checks for MSVC compiler version.
+ *
+ * If the MSVC version is less than 2017, an error is raised.
+ */
+#if defined(_MSC_VER) && _MSC_VER < 1910
+#error "Requires MSVC 2017 or newer!"
+/**
+ * @brief Checks for Clang compiler version.
+ *
+ * If the Clang version is less than 6, an error is raised.
+ */
+#elif defined(__clang__) && __clang_major__ < 6
+#error "Requires clang 6 or newer!"
+/**
+ * @brief Checks for GCC compiler version.
+ *
+ * If the GCC version is less than 9 and it is not Clang, an error is raised.
+ */
+#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 9
+#error "Requires gcc 9 or newer!"
+/**
+ * @brief Checks for unsupported compilers.
+ *
+ * If the compiler is not MSVC, Clang, or GCC, an error is raised.
+ */
+#elif !defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
+#error "Your compiler is not supported!"
+#endif
+
+/**
+ * @brief Defines the MGUTILITY_CPLUSPLUS macro for MSVC and other compilers.
+ *
+ * For MSVC, it uses _MSVC_LANG. For other compilers, it uses __cplusplus.
+ */
+#ifdef _MSC_VER
+#define __PRETTY_FUNCTION__ __FUNCSIG__
+#endif
+
+namespace mgutility
+{
+ namespace detail
+ {
+
+ struct enum_type
+ {
+ /**
+ * @brief Gets the name of an unscoped enum value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam e The enum value.
+ * @return A string view representing the name of the enum value.
+ */
+ template <
+ typename Enum, Enum e,
+ detail::enable_if_t::value, bool> = true>
+ MGUTILITY_CNSTXPR static auto name() noexcept -> mgutility::string_view
+ {
+ auto str = mgutility::string_view(__PRETTY_FUNCTION__);
+ auto offset = lastidxenumname[0] + lastidxenumname[1];
+ auto index = std::max(str.rfind(lastidxenumname[2], str.size() - offset),
+ str.rfind(lastidxenumname[3], str.size() - offset));
+ auto result = str.substr(index + 1, str.size() - offset - index);
+ return result[0] == '(' ? "" : result;
+ }
+
+ /**
+ * @brief Gets the name of a scoped enum value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam e The enum value.
+ * @return A string view representing the name of the enum value.
+ */
+ template <
+ typename Enum, Enum e,
+ detail::enable_if_t::value, bool> = true>
+ MGUTILITY_CNSTXPR static auto name() noexcept -> mgutility::string_view
+ {
+ auto str = mgutility::string_view(__PRETTY_FUNCTION__);
+ auto index =
+ str.rfind(lastidxenumname[3], str.size() - lastidxenumname[0]) + 1;
+ auto result = str.substr(index, str.size() - lastidxenumname[0] - index);
+ return result.size() > 4 && result[4] == lastidxenumname[4] ? "" : result;
+ }
+
+ private:
+ static constexpr int lastidxenumname[] =
+#if defined(__clang__)
+ {1, 1, ' ', ':', '('};
+#elif defined(_MSC_VER)
+ {21, 0, ',', ':', '<'};
+#elif defined(__GNUC__)
+ {
+#if MGUTILITY_CPLUSPLUS < 201703L
+ 163,
+#else
+ 157,
+#endif
+ 5, ' ', ':', '('};
+#endif
+ };
+
+ /**
+ * @brief Generates an array of enum names.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Is The enumeration values.
+ * @return An array of string views representing the enum names.
+ */
+ template
+ MGUTILITY_CNSTXPR inline auto
+ get_enum_array(detail::enum_sequence /*unused*/) noexcept
+ -> std::array
+ {
+ return std::array{
+ "", enum_type::template name()...};
+ }
+
+ /**
+ * @brief Generates an array of enum names.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Min The minimum enum value.
+ * @tparam Max The maximum enum value.
+ * @return An array of string views representing the enum names.
+ */
+ template ::min, int Max = mgutility::enum_range::max>
+ MGUTILITY_CNSTXPR inline auto
+ get_enum_array() noexcept
+ -> std::array
+ {
+ return get_enum_array(detail::make_enum_sequence());
+ }
+
+ /**
+ * @brief Converts a string to an enum value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Min The minimum enum value.
+ * @tparam Max The maximum enum value.
+ * @param str The string view representing the enum name.
+ * @return An optional enum value.
+ */
+ template
+ MGUTILITY_CNSTXPR inline auto to_enum_impl(mgutility::string_view str) noexcept
+ -> mgutility::optional
+ {
+ MGUTILITY_CNSTXPR auto arr =
+ get_enum_array();
+ const auto index{std::find(arr.begin() + 1, arr.end(), str)};
+ return index == arr.end() ? mgutility::nullopt
+ : mgutility::optional{static_cast(
+ std::distance(arr.begin(), index) + Min - 1)};
+ }
+
+ /**
+ * @brief Converts a string to an enum bitmask value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Min The minimum enum value.
+ * @tparam Max The maximum enum value.
+ * @param str The string view representing the enum name.
+ * @return An optional enum bitmask value.
+ */
+ template
+ MGUTILITY_CNSTXPR auto to_enum_bitmask_impl(mgutility::string_view str) noexcept
+ -> mgutility::optional
+ {
+
+ // Check if the string contains a '|' character
+ if (str.find('|') == mgutility::string_view::npos)
+ {
+ return to_enum_impl(str);
+ }
+
+ mgutility::optional result{mgutility::nullopt};
+ std::size_t index = 0;
+
+ for (std::size_t i = 0; i < str.size(); ++i)
+ {
+ if (str[i] == '|')
+ {
+ auto name = str.substr(index, i - index);
+ auto maybe_enum = to_enum_impl(name);
+
+ if (!name.empty() && maybe_enum)
+ {
+ result.emplace(result ? static_cast(*result | *maybe_enum)
+ : *maybe_enum);
+ }
+
+ index = i + 1;
+ }
+ }
+
+ auto maybe_enum = to_enum_impl(str.substr(index));
+ if (result && maybe_enum)
+ {
+ result.emplace(static_cast(*result | *maybe_enum));
+ }
+ else
+ {
+ result.reset();
+ }
+
+ return result;
+ }
+
+ /**
+ * @brief Gets the name of an enum value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Min The minimum enum value.
+ * @tparam Max The maximum enum value.
+ * @param e The enum value.
+ * @return A string view representing the name of the enum value.
+ */
+ template ::value, bool> = true>
+ MGUTILITY_CNSTXPR auto enum_name_impl(Enum e) noexcept
+ -> mgutility::string_view
+ {
+ MGUTILITY_CNSTXPR auto arr =
+ get_enum_array();
+ const auto index{(Min < 0 ? Min * -1 : Min) + static_cast(e) + 1};
+ return arr[(index < Min || index > arr.size() - 1) ? 0 : index];
+ }
+
+ /**
+ * @brief Gets the name of an enum bitmask value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Min The minimum enum value.
+ * @tparam Max The maximum enum value.
+ * @param e The enum value.
+ * @return A string view or string representing the name of the enum bitmask
+ * value.
+ */
+ template ::value, bool> = true>
+ MGUTILITY_CNSTXPR_CLANG_WA inline auto enum_name_impl(Enum e) noexcept
+ -> detail::string_or_view_t
+ {
+
+ // Get the array of enum names
+ MGUTILITY_CNSTXPR auto arr =
+ get_enum_array();
+
+ // Calculate the index in the array
+ const auto index = (Min < 0 ? -Min : Min) + static_cast(e) + 1;
+ const auto name =
+ arr[(index < Min || index >= static_cast(arr.size())) ? 0 : index];
+
+ // Lambda to check if a character is a digit
+ const auto is_digit = [](char c)
+ { return c >= '0' && c <= '9'; };
+
+ // Return the name if it's valid
+ if (!name.empty() && !is_digit(name[0]))
+ {
+ return std::string{name};
+ }
+
+ // Construct bitmasked name
+ std::string bitmasked_name;
+ for (auto i = Min; i < Max; ++i)
+ {
+ const auto idx = (Min < 0 ? -Min : Min) + i + 1;
+ if (idx >= 0 && idx < static_cast(arr.size()) && !arr[idx].empty() &&
+ !is_digit(arr[idx][0]) &&
+ (e & static_cast(i)) == static_cast(i))
+ {
+ bitmasked_name.append(arr[idx]).append("|");
+ }
+ }
+
+ // Remove the trailing '|' if present
+ if (!bitmasked_name.empty())
+ {
+ bitmasked_name.pop_back();
+ }
+
+ return bitmasked_name.find('|') != std::string::npos ? bitmasked_name
+ : std::string{""};
+ }
+ } // namespace detail
+} // namespace mgutility
+
+#endif // DETAIL_ENUM_NAME_IMPL_HPP
\ No newline at end of file
diff --git a/include/mgutility/reflection/detail/meta.hpp b/include/mgutility/reflection/detail/meta.hpp
new file mode 100644
index 0000000..fd39c8e
--- /dev/null
+++ b/include/mgutility/reflection/detail/meta.hpp
@@ -0,0 +1,167 @@
+/*
+MIT License
+
+Copyright (c) 2024 mguludag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+
+
+#ifndef DETAIL_META_HPP
+#define DETAIL_META_HPP
+
+#include "mgutility/_common/definitions.hpp"
+#include
+
+namespace mgutility {
+ namespace detail {
+ /**
+ * @brief Trait to check if a type is a scoped enumeration.
+ *
+ * @tparam E The type to check.
+ */
+ template
+ struct is_scoped_enum {
+ /**
+ * @brief Boolean value indicating if the type is a scoped enumeration.
+ */
+ static constexpr auto value = std::is_enum::value &&
+ !std::is_convertible::type>::value;
+ };
+
+ /**
+ * @brief Trait to check if a type supports the bitwise OR operator.
+ *
+ * @tparam T The type to check.
+ * @tparam Enable SFINAE parameter, default is void.
+ */
+ template
+ struct has_bit_or : std::false_type {
+ };
+
+ /**
+ * @brief Specialization of has_bit_or for types that support the bitwise OR operator.
+ *
+ * @tparam T The type to check.
+ */
+ template
+ struct has_bit_or : std::true_type {
+ };
+
+#if MGUTILITY_CPLUSPLUS > 201103L
+ /**
+ * @brief Helper variable template for is_scoped_enum.
+ *
+ * @tparam E The type to check.
+ */
+ template
+ static constexpr bool is_scoped_enum_v = is_scoped_enum::value;
+#endif
+
+ /**
+ * @brief Alias template for std::enable_if.
+ *
+ * This template is used to conditionally enable a type `T` if the boolean constant `B` is true.
+ * It is a shorthand for `typename std::enable_if::type`.
+ *
+ * @tparam B The compile-time boolean condition.
+ * @tparam T The type to be enabled if `B` is true, default is void.
+ */
+ template
+ using enable_if_t = typename std::enable_if::type;
+
+ /**
+ * @brief Alias template for std::underlying_type.
+ *
+ * @tparam T The enumeration type.
+ */
+ template
+ using underlying_type_t = typename std::underlying_type::type;
+
+ /**
+ * @brief Alias template for std::remove_const.
+ *
+ * @tparam T The type to remove const from.
+ */
+ template
+ using remove_const_t = typename std::remove_const::type;
+
+ /**
+ * @brief Represents a sequence of enumeration values.
+ *
+ * @tparam Enum The enumeration type.
+ * @tparam ...EnumValues The enumeration values in the sequence.
+ */
+ template
+ struct enum_sequence {
+ };
+
+ /**
+ * @brief Helper for generating a sequence of enumeration values.
+ *
+ * @tparam Enum The enumeration type.
+ * @tparam Min The minimum value in the sequence.
+ * @tparam Max The maximum value in the sequence.
+ * @tparam ...Next The next values in the sequence.
+ */
+ template
+ struct enum_sequence_helper
+ : enum_sequence_helper {
+ };
+
+ /**
+ * @brief Specialization of enum_sequence_helper for the end of the sequence.
+ *
+ * @tparam Enum The enumeration type.
+ * @tparam Min The minimum value in the sequence.
+ * @tparam ...Next The next values in the sequence.
+ */
+ template
+ struct enum_sequence_helper {
+ /**
+ * @brief The resulting sequence type.
+ */
+ using type = enum_sequence(Next)...>;
+ };
+
+ /**
+ * @brief Generates a sequence of enumeration values.
+ *
+ * @tparam Enum The enumeration type.
+ * @tparam Min The minimum value in the sequence.
+ * @tparam Max The maximum value in the sequence.
+ */
+ template
+ using make_enum_sequence = typename enum_sequence_helper::type;
+ } // namespace detail
+
+ /**
+ * @brief Provides the range for an enumeration type.
+ *
+ * @tparam T The enumeration type.
+ */
+ template
+ struct enum_range {
+ static constexpr auto min{0};
+ static constexpr auto max{256};
+ };
+} // namespace mgutility
+
+#endif // DETAIL_META_HPP
\ No newline at end of file
diff --git a/include/mgutility/reflection/enum_name.hpp b/include/mgutility/reflection/enum_name.hpp
new file mode 100644
index 0000000..c88b042
--- /dev/null
+++ b/include/mgutility/reflection/enum_name.hpp
@@ -0,0 +1,206 @@
+/*
+MIT License
+
+Copyright (c) 2023 mguludag
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef MGUTILITY_ENUM_NAME_HPP
+#define MGUTILITY_ENUM_NAME_HPP
+
+#include "detail/enum_name_impl.hpp"
+
+namespace mgutility
+{
+
+ /**
+ * @brief Converts an enum value to its underlying integer value.
+ *
+ * @tparam Enum The enum type.
+ * @param e The enum value.
+ * @return The underlying integer value of the enum.
+ */
+ template
+ constexpr auto enum_to_underlying(Enum e) noexcept
+ -> detail::underlying_type_t
+ {
+ static_assert(std::is_enum::value, "Value is not an Enum type!");
+ return static_cast>(e);
+ }
+
+ /**
+ * @brief Gets the name of an enum value.
+ *
+ * @tparam Min The minimum enum value.
+ * @tparam Max The maximum enum value.
+ * @tparam Enum The enum type.
+ * @param e The enum value.
+ * @return A string view or string representing the name of the enum value.
+ */
+ template
+ MGUTILITY_CNSTXPR auto enum_name(Enum e) noexcept
+ -> detail::string_or_view_t
+ {
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum::value, "Value is not an Enum type!");
+ return detail::enum_name_impl(e);
+ }
+
+ /**
+ * @brief Gets the name of an enum value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Min The minimum enum value, default is enum_range::min.
+ * @tparam Max The maximum enum value, default is enum_range::max.
+ * @param e The enum value.
+ * @return A string view or string representing the name of the enum value.
+ */
+ template ::min,
+ int Max = enum_range::max>
+ MGUTILITY_CNSTXPR auto enum_name(Enum e) noexcept
+ -> detail::string_or_view_t
+ {
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum::value, "Value is not an Enum type!");
+ return detail::enum_name_impl(e);
+ }
+
+ /**
+ * @brief Gets the enum value and its name.
+ *
+ * @tparam Enum The enum type.
+ * @return A pair of the enum value and its name.
+ */
+ template
+ auto enum_for_each::enum_iter::operator*() const -> value_type
+ {
+ auto value = static_cast(m_pos);
+ return detail::enum_pair{value, enum_name(value)};
+ }
+
+ /**
+ * @brief Converts a string to an enum value.
+ *
+ * @tparam Enum The enum type.
+ * @tparam Min The minimum enum value, default is enum_range::min.
+ * @tparam Max The maximum enum value, default is enum_range::max.
+ * @param str The string view representing the enum name.
+ * @return An optional enum value.
+ */
+ template ::min,
+ int Max = enum_range::max,
+ detail::enable_if_t::value, bool> = true>
+ MGUTILITY_CNSTXPR auto to_enum(mgutility::string_view str) noexcept
+ -> mgutility::optional
+ {
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum