#pragma once #include "common.hpp" #include "details/optional.hpp" #include "enchantum.hpp" #include namespace enchantum { namespace details { template struct next_value_functor { template [[nodiscard]] constexpr optional operator()(const E value, const std::ptrdiff_t n = 1) const noexcept { if (!enchantum::contains(value)) return optional{}; const auto index = static_cast(*enchantum::enum_to_index(value)) + (n * N); if (index >= 0 && index < static_cast(count)) return optional{values[static_cast(index)]}; return optional{}; } }; template struct next_value_circular_functor { template [[nodiscard]] constexpr E operator()(const E value, const std::ptrdiff_t n = 1) const noexcept { ENCHANTUM_ASSERT(enchantum::contains(value), "next/prev_value_circular requires 'value' to be a valid enum member", value); const auto i = static_cast(*enchantum::enum_to_index(value)); constexpr auto count = static_cast(enchantum::count); return values[static_cast(((i + (n * N)) % count + count) % count)]; // handles wrap around and negative n } }; } // namespace details inline constexpr details::next_value_functor<1> next_value{}; inline constexpr details::next_value_functor<-1> prev_value{}; inline constexpr details::next_value_circular_functor<1> next_value_circular{}; inline constexpr details::next_value_circular_functor<-1> prev_value_circular{}; } // namespace enchantum