diff --git a/include/enum_name.hpp b/include/enum_name.hpp index ad15ebf..4ad394c 100644 --- a/include/enum_name.hpp +++ b/include/enum_name.hpp @@ -64,535 +64,445 @@ #endif namespace mgutility { - namespace detail { +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 - 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 underlying_type_t = typename std::underlying_type::type; +template +using remove_const_t = typename std::remove_const::type; - template - using remove_const_t = typename std::remove_const::type; +#if MG_ENUM_NAME_CPLUSPLUS < 201703L - #if MG_ENUM_NAME_CPLUSPLUS < 201703L +template +using enable_if_t = typename std::enable_if::type; - 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); +} - 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); + } - 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< - typename U = T, - enable_if_t::value, bool> = true> - MG_ENUM_NAME_CNSTXPR inline void reset() - { - T::~T(); - has_value_ = false; - } - #endif - template< - typename U = T, - enable_if_t::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::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::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 __for_each_to_enum_impl(detail::string_view str, int Min, detail::enum_sequence) noexcept - -> detail::optional - { - using array = std::array; - MG_ENUM_NAME_CNSTXPR static array arr{"", enum_type::template name()...}; - 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)}; - } + 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; + } - template - inline auto __for_each_enum_impl(Enum e, int Min, int Max, detail::enum_sequence) noexcept - -> detail::string_view - { - using array = std::array; - MG_ENUM_NAME_CNSTXPR static array arr{"", enum_type::template name()...}; - const auto index{std::abs(Min) + static_cast(e) + (Min < 0 ? 1 : 1)}; - return arr[(index < Min || index > arr.size() - 1) ? 0 : index]; + 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; } - } // namespace detail -} // namespace mgutility - - namespace mgutility { - template - struct enum_range { - static constexpr auto min{-128}; - static constexpr auto max{128}; + 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_; +}; - 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& +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__) { - return m_begin; +#if MG_ENUM_NAME_CPLUSPLUS < 201703L + 179, +#else + 165, +#endif + 5, ' ', ':', '('}; +#endif +}; + +template +using enum_pair = std::pair; + +template +MG_ENUM_NAME_CNSTXPR inline auto get_enum_array( + detail::enum_sequence) noexcept + -> std::array { + MG_ENUM_NAME_CNSTXPR static std::array + arr{"", enum_type::template name()...}; + return arr; +} + +template +inline auto to_enum_impl(detail::string_view str) noexcept + -> detail::optional { + MG_ENUM_NAME_CNSTXPR 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 { + MG_ENUM_NAME_CNSTXPR 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 end() -> enum_iter& - { - return m_end; + + auto operator++(int) -> enum_iter { + m_pos++; + return *this; } - auto size() -> std::size_t - { - return enum_range::max - enum_range::min; + + auto operator!=(const enum_iter& other) const -> bool { + return m_pos != other.m_pos; } - private: - enum_iter m_begin{enum_range::min}; - enum_iter m_end{enum_range::max}; + auto operator==(const enum_iter& other) const -> bool { + return m_pos == other.m_pos; + } + + auto operator*() const -> value_type; + + private: + iter_type m_pos; }; - 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); + 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; } - 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 __for_each_enum_impl(e, Min, Max, mgutility::detail::make_enum_sequence()); - } + private: + enum_iter m_begin{enum_range::min}; + enum_iter m_end{enum_range::max}; +}; - 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 __for_each_enum_impl(e, Min, Max, mgutility::detail::make_enum_sequence()); - } +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 - 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 +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 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 __for_each_to_enum_impl(str, Min, detail::make_enum_sequence()); - } -} // namespace mgutility +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& -{ +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 +#endif // MGUTILITY_ENUM_NAME_HPP