// __ __ _ ______ _____ // | \/ | (_) | ____| / ____|_ _ // | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_ // | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _| // | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_| // |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____| // __/ | https://github.com/Neargye/magic_enum // |___/ version 0.9.8 // // Licensed under the MIT License . // SPDX-License-Identifier: MIT // Copyright (c) 2019 - 2026 Daniil Goncharov . // // 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 NEARGYE_MAGIC_ENUM_UTILITY_HPP #define NEARGYE_MAGIC_ENUM_UTILITY_HPP #include "magic_enum.hpp" #ifndef MAGIC_ENUM_USE_STD_MODULE # include #endif namespace magic_enum { namespace detail { template using enum_for_each_result_t = std::decay_t[J]>>>; template constexpr auto for_each(F&& f, std::index_sequence) { constexpr bool has_void_return = (std::is_void_v[J]>>> || ...); constexpr bool all_same_return = (std::is_same_v[0]>>, std::invoke_result_t[J]>>> && ...); if constexpr (has_void_return) { (detail::invoke_constant(f, enum_constant[J]>{}), ...); } else if constexpr (all_same_return) { return std::array, sizeof...(J)>{{detail::invoke_constant(f, enum_constant[J]>{})...}}; } else { return std::tuple...>{detail::invoke_constant(f, enum_constant[J]>{})...}; } } template constexpr bool all_invocable(std::index_sequence) { if constexpr (count_v == 0) { return false; } else { return (std::is_invocable_v[J]>> && ...); } } } // namespace magic_enum::detail template , typename F, detail::enable_if_t = 0> constexpr auto enum_for_each(F&& f) { using D = std::decay_t; static_assert(std::is_enum_v, "magic_enum::enum_for_each requires enum type."); static_assert(detail::is_reflected_v, "magic_enum requires enum implementation and valid max and min."); constexpr auto sep = std::make_index_sequence>{}; if constexpr (detail::all_invocable(sep)) { return detail::for_each(std::forward(f), sep); } else { static_assert(detail::always_false_v, "magic_enum::enum_for_each requires invocable of all enum value."); } } template > [[nodiscard]] constexpr auto enum_next_value(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t>> { using D = std::decay_t; constexpr std::ptrdiff_t count = detail::count_v; if (const auto i = enum_index(value)) { const auto index = static_cast(*i); if ((n > 0 && n >= count - index) || (n < 0 && n < -index)) { return {}; } return enum_value(static_cast(index + n)); } return {}; } template > [[nodiscard]] constexpr auto enum_next_value_circular(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t> { using D = std::decay_t; constexpr std::ptrdiff_t count = detail::count_v; if (const auto i = enum_index(value)) { auto index = (static_cast(*i) + (n % count)) % count; if (index < 0) { index += count; } return enum_value(static_cast(index)); } return MAGIC_ENUM_ASSERT(false), value; } template > [[nodiscard]] constexpr auto enum_prev_value(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t>> { using D = std::decay_t; constexpr std::ptrdiff_t count = detail::count_v; if (const auto i = enum_index(value)) { const auto index = static_cast(*i); if ((n > 0 && n > index) || (n < 0 && n <= index - count)) { return {}; } return enum_value(static_cast(index - n)); } return {}; } template > [[nodiscard]] constexpr auto enum_prev_value_circular(E value, std::ptrdiff_t n = 1) noexcept -> detail::enable_if_t> { using D = std::decay_t; constexpr std::ptrdiff_t count = detail::count_v; if (const auto i = enum_index(value)) { auto index = (static_cast(*i) - (n % count)) % count; if (index < 0) { index += count; } return enum_value(static_cast(index)); } return MAGIC_ENUM_ASSERT(false), value; } } // namespace magic_enum #endif // NEARGYE_MAGIC_ENUM_UTILITY_HPP