From 11a03664214df9ae0248f6dc72ce25b97b4837d5 Mon Sep 17 00:00:00 2001 From: neargye Date: Mon, 8 Apr 2019 14:58:30 +0500 Subject: [PATCH] v0.4.0 --- CMakeLists.txt | 2 +- README.md | 65 +++++++++------- example/example.cpp | 16 ++-- include/magic_enum.hpp | 114 +++++++++++++++------------ test/test.cpp | 169 +++++++++++++++++++++-------------------- 5 files changed, 198 insertions(+), 168 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4efc7b..594a081 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.6) -project(magic_enum VERSION "0.3.0" LANGUAGES CXX) +project(magic_enum VERSION "0.4.0" LANGUAGES CXX) option(MAGIC_ENUM_OPT_BUILD_EXAMPLES "Build magic_enum examples" ON) option(MAGIC_ENUM_OPT_BUILD_TESTS "Build and perform magic_enum tests" ON) diff --git a/README.md b/README.md index b15a19d..3a20c06 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,17 @@ [![Build Status](https://travis-ci.org/Neargye/magic_enum.svg?branch=master)](https://travis-ci.org/Neargye/magic_enum) [![Build status](https://ci.appveyor.com/api/projects/status/0rpr966p9ssrvwu3/branch/master?svg=true)](https://ci.appveyor.com/project/Neargye/magic-enum-hf8vk/branch/master) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/64d04f150af14c3e8bd1090057b68538)](https://www.codacy.com/app/Neargye/magic_enum?utm_source=github.com&utm_medium=referral&utm_content=Neargye/magic_enum&utm_campaign=Badge_Grade) -[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/kXdow0AxI1Dss18p) +[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/jPWeZxV1UcqvudZr) ## What is Magic Enum? -Header-only C++17 library provides Enum-to-String and String-to-Enum and other useful, functions work with any enum type without any macro or boilerplate code. -* `yae::enum_cast` obtains enum value from string or integer. -* `yae::enum_value` obtains indexed access to enum value. -* `yae::enum_values` obtains enum value sequence. -* `yae::enum_count` obtains number of enum values. -* `yae::enum_name` obtains string name from enum value. -* `yae::enum_names` obtains string enum name sequence. +Header-only C++17 library provides static reflection on enums, work with any enum type without any macro or boilerplate code. +* `enum_cast` obtains enum value from string or integer. +* `enum_value` returns enum value at specified index. +* `enum_values` obtains enum value sequence. +* `enum_count` returns number of enum values. +* `enum_name` obtains string name from enum value. +* `enum_names` obtains string enum name sequence. ## Features @@ -34,6 +34,7 @@ Header-only C++17 library provides Enum-to-String and String-to-Enum and other u * Header-only * Dependency-free * Compile-time +* Static reflection on enums * Enum to string * String to enum * Work with any enum type @@ -49,7 +50,7 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * Enum value to string ```cpp Color color = Color::RED; - auto color_name = yae::enum_name(color); + auto color_name = magic_enum::enum_name(color); if (color_name.has_value()) { // color_name.value() -> "RED" } @@ -58,7 +59,7 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * Static storage enum variable to string ```cpp constexpr Color color = Color::BLUE; - constexpr auto color_name = yae::enum_name(color); + constexpr auto color_name = magic_enum::enum_name(color); if (color_name.has_value()) { // color_name.value() -> "BLUE" } @@ -67,7 +68,7 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * String to enum value ```cpp std::string color_name{"GREEN"}; - auto color = yae::enum_cast(color_name); + auto color = magic_enum::enum_cast(color_name); if (color.has_value()) { // color.value() -> Color::GREEN } @@ -75,7 +76,7 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * Static storage string to enum value ```cpp - constexpr auto color = yae::enum_cast("BLUE"); + constexpr auto color = magic_enum::enum_cast("BLUE"); if (color.has_value()) { // color.value() -> Color::BLUE } @@ -84,7 +85,7 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * Integer to enum value ```cpp int color_value = 2; - auto color = yae::enum_cast(color_value); + auto color = magic_enum::enum_cast(color_value); if (colo.has_value()) { // color.value() -> Color::RED } @@ -92,7 +93,7 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * Static storage integer to enum value ```cpp - constexpr auto color = yae::enum_cast(4); + constexpr auto color = magic_enum::enum_cast(4); if (color.has_value()) { // color.value() -> Color::BLUE } @@ -101,55 +102,67 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; * Indexed access to enum value ```cpp int i = 1; - Color colo = yae::enum_value(i); + Color colo = magic_enum::enum_value(i); // color -> Color::BLUE ``` * Compile-time indexed access. ```cpp - constexpr Color color = yae::enum_value(0); + constexpr Color color = magic_enum::enum_value(0); // color -> Color::RED ``` * Enum value sequence ```cpp - constexpr auto colors = yae::enum_values(); + constexpr auto colors = magic_enum::enum_values(); // colors -> {Color::RED, Color::BLUE, Color::GREEN} ``` * Number of enum elements ```cpp - constexpr std::size_t color_count = yae::enum_count(); + constexpr std::size_t color_count = magic_enum::enum_count(); // color_count -> 3 ``` * Enum names sequence ```cpp - constexpr auto color_names = yae::enum_names(); + constexpr auto color_names = magic_enum::enum_names(); // color_names -> {"RED", "BLUE", "GREEN"} ``` * Stream operator for enum ```cpp - using namespace yae::ops; // out-of-the-box stream operator for enums. + using namespace magic_enum::ops; // out-of-the-box stream operator for enums. Color color = Color::BLUE; std::cout << color << std::endl; // "BLUE" ``` ## Remarks -* `yae::enum_cast` returns `std::optional`, using `has_value()` to check contains enum value and `value()` to get the enum value. +* `magic_enum::enum_cast` returns `std::optional`, using `has_value()` to check contains enum value and `value()` to get the enum value. -* `yae::enum_values` returns `std::array` with all enum value where `N = number of enum values`, sorted by enum value. +* `magic_enum::enum_value` no bounds checking is performed: the behavior is undefined if `index >= number of enum values`. -* `yae::enum_name` returns `std::optional`, using `has_value()` to check contains enum name and `value()` to get the enum name. +* `magic_enum::enum_values` returns `std::array` with all enum value where `N = number of enum values`, sorted by enum value. -* `yae::enum_names` returns `std::array` with all string enum name where `N = number of enum values`, sorted by enum value. +* `magic_enum::enum_name` returns `std::optional`, using `has_value()` to check contains enum name and `value()` to get the enum name. -* Enum value must be in range `(-MAGIC_ENUM_RANGE, MAGIC_ENUM_RANGE)`. By default `MAGIC_ENUM_RANGE = 256`. If you need a larger range, redefine the macro `MAGIC_ENUM_RANGE`. +* `magic_enum::enum_names` returns `std::array` with all string enum name where `N = number of enum values`, sorted by enum value. + +* Enum value must be in range `[-256, 256]`. If you need another range, add specialization enum_range for necessary enum type. ```cpp - #define MAGIC_ENUM_RANGE 1024 // Redefine MAGIC_ENUM_RANGE for larger range. #include + + enum number { one = 100, two = 200, three = 300 }; + + namespace magic_enum { + template <> + struct enum_range { + static constexpr int min = 100; + static constexpr int max = 300; + }; + } + ``` ## Integration diff --git a/example/example.cpp b/example/example.cpp index 6dcefd9..07bf4ad 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -29,13 +29,13 @@ enum Color { RED = -10, BLUE = 0, GREEN = 10 }; int main() { // Enum variable to string name. Color c1 = Color::RED; - auto c1_name = yae::enum_name(c1); + auto c1_name = magic_enum::enum_name(c1); if (c1_name.has_value()) { std::cout << c1_name.value() << std::endl; // RED } // String enum name sequence. - constexpr auto color_names = yae::enum_names(); + constexpr auto color_names = magic_enum::enum_names(); std::cout << "Color names:"; for (auto n : color_names) { std::cout << " " << n; @@ -44,29 +44,29 @@ int main() { // Color names: RED BLUE GREEN // String name to enum value. - auto c2 = yae::enum_cast("BLUE"); + auto c2 = magic_enum::enum_cast("BLUE"); if (c2.has_value() && c2.value() == Color::BLUE) { std::cout << "BLUE = " << c2.value() << std::endl; // BLUE = 0 } // Integer value to enum value. - auto c3 = yae::enum_cast(10); + auto c3 = magic_enum::enum_cast(10); if (c3.has_value() && c3.value() == Color::GREEN) { std::cout << "GREEN = " << c3.value() << std::endl; // GREEN = 10 } - using namespace yae::ops; // out-of-the-box stream operator for enums. + using namespace magic_enum::ops; // out-of-the-box stream operator for enums. // ostream operator for enum. std::cout << "Color: " << c1 << " " << c2 << " " << c3 << std::endl; // Color: RED BLUE GREEN // Number of enum values. - std::cout << "Color enum size: " << yae::enum_count() << std::endl; // Color enum size: 3 + std::cout << "Color enum size: " << magic_enum::enum_count() << std::endl; // Color enum size: 3 // Indexed access to enum value. - std::cout << "Color[0] = " << yae::enum_value(0) << std::endl; // Color[0] = RED + std::cout << "Color[0] = " << magic_enum::enum_value(0) << std::endl; // Color[0] = RED // Enum value sequence. - constexpr auto colors = yae::enum_values(); + constexpr auto colors = magic_enum::enum_values(); std::cout << "Colors sequence:"; for (Color c : colors) { std::cout << " " << c; // ostream operator for enum. diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 2459f9f..969fe9f 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -5,7 +5,7 @@ // | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_| // |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____| // __/ | https://github.com/Neargye/magic_enum -// |___/ vesion 0.3.0 +// |___/ vesion 0.4.0 // // Licensed under the MIT License . // SPDX-License-Identifier: MIT @@ -31,7 +31,6 @@ #pragma once -#include #include #include #include @@ -42,34 +41,44 @@ #include #include -// Enum value must be in range (-MAGIC_ENUM_RANGE, MAGIC_ENUM_RANGE). If you need a larger range, redefine the macro MAGIC_ENUM_RANGE. -#if !defined(MAGIC_ENUM_RANGE) -# define MAGIC_ENUM_RANGE 256 -#endif +namespace magic_enum { -namespace yae { // aka Yet Another Enums. - -static_assert(MAGIC_ENUM_RANGE > 0, - "MAGIC_ENUM_RANGE must be positive and greater than zero."); -static_assert(MAGIC_ENUM_RANGE < std::numeric_limits::max(), - "MAGIC_ENUM_RANGE must be less INT_MAX."); +// Enum value must be in range [-256, 256]. If you need another range, add specialization enum_range for necessary enum type. +template +struct enum_range final { + static_assert(std::is_enum_v, "magic_enum::enum_range requires enum type."); + static constexpr int min = std::is_signed_v> ? -256 : 0; + static constexpr int max = 256; +}; namespace detail { template -struct enum_range final { - using D = std::decay_t; - static_assert(std::is_enum_v, "yae::detail::enum_range require enum type."); - using U = std::underlying_type_t; - using C = std::common_type_t; - static constexpr int min = std::max(std::is_signed_v ? -MAGIC_ENUM_RANGE : 0, std::numeric_limits::min()); - static constexpr int max = std::min(MAGIC_ENUM_RANGE, std::numeric_limits::max()); - static constexpr auto sequence = std::make_integer_sequence{}; +[[nodiscard]] constexpr int min_impl() { + static_assert(std::is_enum_v, "magic_enum::detail::min_impl requires enum type."); + using U = std::underlying_type_t; + constexpr int min = (enum_range::min > std::numeric_limits::min()) ? enum_range::min : std::numeric_limits::min(); + + return min; +} + +template +[[nodiscard]] constexpr int max_impl() { + static_assert(std::is_enum_v, "magic_enum::detail::max_impl requires enum type."); + using U = std::underlying_type_t; + constexpr int max = (enum_range::max < std::numeric_limits::max()) ? enum_range::max : std::numeric_limits::max(); + + return max; +} + +template +[[nodiscard]] constexpr decltype(auto) range_impl() { + static_assert(std::is_enum_v, "magic_enum::detail::range_impl requires enum type."); + constexpr auto range = std::make_integer_sequence() - min_impl() + 1>{}; + + return range; +} - static constexpr bool contains(int value) noexcept { - return static_cast(value) <= enum_range::max && static_cast(value) >= enum_range::min; - } -}; [[nodiscard]] constexpr bool is_name_char(char c, bool front) noexcept { return (!front && c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; @@ -77,7 +86,7 @@ struct enum_range final { template [[nodiscard]] constexpr std::string_view name_impl() noexcept { - static_assert(std::is_enum_v, "yae::detail::name_impl require enum type."); + static_assert(std::is_enum_v, "magic_enum::detail::name_impl requires enum type."); #if defined(__clang__) std::string_view name{__PRETTY_FUNCTION__}; constexpr auto suffix = sizeof("]") - 1; @@ -110,31 +119,36 @@ template template [[nodiscard]] constexpr decltype(auto) strings_impl(std::integer_sequence) noexcept { - static_assert(std::is_enum_v, "yae::detail::strings_impl require enum type."); - constexpr std::array names{{name_impl(I + enum_range::min)>()...}}; + static_assert(std::is_enum_v, "magic_enum::detail::strings_impl requires enum type."); + constexpr std::array names{{name_impl(I + min_impl())>()...}}; return names; } template [[nodiscard]] constexpr std::string_view name_impl(int value) noexcept { - static_assert(std::is_enum_v, "yae::detail::name_impl require enum type."); - constexpr auto names = strings_impl(enum_range::sequence); + static_assert(std::is_enum_v, "magic_enum::detail::name_impl requires enum type."); + constexpr auto names = strings_impl(range_impl()); + const int i = value - min_impl(); - return enum_range::contains(value) ? names[value - enum_range::min] : std::string_view{}; + if (i >= 0 && static_cast(i) < names.size()) { + return names[i]; + } else { + return {}; + } } template [[nodiscard]] constexpr decltype(auto) values_impl(std::integer_sequence) noexcept { - static_assert(std::is_enum_v, "yae::detail::values_impl require enum type."); + static_assert(std::is_enum_v, "magic_enum::detail::values_impl requires enum type."); constexpr int n = sizeof...(I); - constexpr std::array valid{{!name_impl(I + enum_range::min)>().empty()...}}; + constexpr std::array valid{{!name_impl(I + min_impl())>().empty()...}}; constexpr int num_valid = ((valid[I] ? 1 : 0) + ...); std::array enums{}; for (int i = 0, v = 0; i < n && v < num_valid; ++i) { if (valid[i]) { - enums[v++] = static_cast(i + enum_range::min); + enums[v++] = static_cast(i + min_impl()); } } @@ -143,8 +157,8 @@ template template [[nodiscard]] constexpr decltype(auto) names_impl(std::integer_sequence) noexcept { - static_assert(std::is_enum_v, "yae::detail::names_impl require enum type."); - constexpr auto enums = values_impl(enum_range::sequence); + static_assert(std::is_enum_v, "magic_enum::detail::names_impl requires enum type."); + constexpr auto enums = values_impl(range_impl()); constexpr std::array names{{name_impl()...}}; return names; @@ -152,8 +166,8 @@ template template [[nodiscard]] constexpr std::optional enum_cast_impl(std::string_view value) noexcept { - static_assert(std::is_enum_v, "yae::detail::enum_cast_impl require enum type."); - constexpr auto values = values_impl(enum_range::sequence); + static_assert(std::is_enum_v, "magic_enum::detail::enum_cast_impl requires enum type."); + constexpr auto values = values_impl(range_impl()); constexpr auto count = values.size(); constexpr auto names = names_impl(std::make_index_sequence{}); @@ -169,7 +183,7 @@ template template using enable_if_enum_t = typename std::enable_if>>::type; -} // namespace yae::detail +} // namespace magic_enum::detail // Obtains enum value from enum string name. template > @@ -191,29 +205,29 @@ template > } } -// Obtains indexed access to enum element. +// Returns enum value at specified index. No bounds checking is performed: the behavior is undefined if index >= number of enum values. template> -[[nodiscard]] constexpr E enum_value(std::size_t i) noexcept { +[[nodiscard]] constexpr E enum_value(std::size_t index) { using D = std::decay_t; - constexpr auto values = detail::values_impl(detail::enum_range::sequence); + constexpr auto values = detail::values_impl(detail::range_impl()); - return assert(i < values.size()), values[i]; + return assert(index < values.size()), values[index]; } // Obtains value enum sequence. template > [[nodiscard]] constexpr decltype(auto) enum_values() noexcept { using D = std::decay_t; - constexpr auto values = detail::values_impl(detail::enum_range::sequence); + constexpr auto values = detail::values_impl(detail::range_impl()); return values; } -// Obtains number of enum elements. +// Returns number of enum values. template > [[nodiscard]] constexpr std::size_t enum_count() noexcept { using D = std::decay_t; - constexpr auto count = detail::values_impl(detail::enum_range::sequence).size(); + constexpr auto count = detail::values_impl(detail::range_impl()).size(); return count; } @@ -225,9 +239,9 @@ template > const auto name = detail::name_impl(static_cast(value)); if (name.empty()) { - return std::nullopt; + return std::nullopt; // Invalid value or out of range. } else { - return name; // Enum value does not have name or out of range. + return name; } } @@ -235,7 +249,7 @@ template > template > [[nodiscard]] constexpr decltype(auto) enum_names() noexcept { using D = std::decay_t; - constexpr auto count = detail::values_impl(detail::enum_range::sequence).size(); + constexpr auto count = detail::values_impl(detail::range_impl()).size(); constexpr auto names = detail::names_impl(std::make_index_sequence{}); return names; @@ -269,6 +283,6 @@ std::ostream& operator<<(std::ostream& os, std::optional value) { return os; } -} // namespace yae::ops +} // namespace magic_enum::ops -} // namespace yae +} // namespace magic_enum diff --git a/test/test.cpp b/test/test.cpp index 9ddaf1a..67588d6 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -23,7 +23,6 @@ #define CATCH_CONFIG_MAIN #include -#define MAGIC_ENUM_RANGE 120 #include #include @@ -36,7 +35,15 @@ enum class Numbers : char { one = 10, two = 20, three = 30 }; enum Directions { Up = 85, Down = -42, Right = 119, Left = -119 }; -enum number : unsigned long { one = 10, two = 20, three = 30 }; +enum number : unsigned long { one = 100, two = 200, three = 300 }; + +namespace magic_enum { +template <> +struct enum_range { + static constexpr int min = 100; + static constexpr int max = 300; +}; +} TEST_CASE("enum_cast") { SECTION("string") { @@ -44,166 +51,162 @@ TEST_CASE("enum_cast") { # define constexpr // Visual Studio 2017 have bug with string_view constexpr compare. #endif - constexpr auto cr = yae::enum_cast("RED"); + constexpr auto cr = magic_enum::enum_cast("RED"); REQUIRE(cr.value() == Color::RED); - REQUIRE(yae::enum_cast("GREEN").value() == Color::GREEN); - REQUIRE(yae::enum_cast("BLUE").value() == Color::BLUE); - REQUIRE_FALSE(yae::enum_cast("None").has_value()); + REQUIRE(magic_enum::enum_cast("GREEN").value() == Color::GREEN); + REQUIRE(magic_enum::enum_cast("BLUE").value() == Color::BLUE); + REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); - constexpr auto no = yae::enum_cast("one"); + constexpr auto no = magic_enum::enum_cast("one"); REQUIRE(no.value() == Numbers::one); - REQUIRE(yae::enum_cast("two").value() == Numbers::two); - REQUIRE(yae::enum_cast("three").value() == Numbers::three); - REQUIRE_FALSE(yae::enum_cast("None").has_value()); + REQUIRE(magic_enum::enum_cast("two").value() == Numbers::two); + REQUIRE(magic_enum::enum_cast("three").value() == Numbers::three); + REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); - constexpr auto dr = yae::enum_cast("Right"); - REQUIRE(yae::enum_cast("Up").value() == Directions::Up); - REQUIRE(yae::enum_cast("Down").value() == Directions::Down); + constexpr auto dr = magic_enum::enum_cast("Right"); + REQUIRE(magic_enum::enum_cast("Up").value() == Directions::Up); + REQUIRE(magic_enum::enum_cast("Down").value() == Directions::Down); REQUIRE(dr.value() == Directions::Right); - REQUIRE(yae::enum_cast("Left").value() == Directions::Left); - REQUIRE_FALSE(yae::enum_cast("None").has_value()); + REQUIRE(magic_enum::enum_cast("Left").value() == Directions::Left); + REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); - constexpr auto nt = yae::enum_cast("three"); - REQUIRE(yae::enum_cast("one").value() == number::one); - REQUIRE(yae::enum_cast("two").value() == number::two); + constexpr auto nt = magic_enum::enum_cast("three"); + REQUIRE(magic_enum::enum_cast("one").value() == number::one); + REQUIRE(magic_enum::enum_cast("two").value() == number::two); REQUIRE(nt.value() == number::three); - REQUIRE_FALSE(yae::enum_cast("None").has_value()); + REQUIRE_FALSE(magic_enum::enum_cast("None").has_value()); #undef constexpr } SECTION("integer") { - constexpr auto cr = yae::enum_cast(-12); + constexpr auto cr = magic_enum::enum_cast(-12); REQUIRE(cr.value() == Color::RED); - REQUIRE(yae::enum_cast(7).value() == Color::GREEN); - REQUIRE(yae::enum_cast(15).value() == Color::BLUE); - REQUIRE_FALSE(yae::enum_cast(0).has_value()); + REQUIRE(magic_enum::enum_cast(7).value() == Color::GREEN); + REQUIRE(magic_enum::enum_cast(15).value() == Color::BLUE); + REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); - constexpr auto no = yae::enum_cast(10); + constexpr auto no = magic_enum::enum_cast(10); REQUIRE(no.value() == Numbers::one); - REQUIRE(yae::enum_cast(20).value() == Numbers::two); - REQUIRE(yae::enum_cast(30).value() == Numbers::three); - REQUIRE_FALSE(yae::enum_cast(0).has_value()); + REQUIRE(magic_enum::enum_cast(20).value() == Numbers::two); + REQUIRE(magic_enum::enum_cast(30).value() == Numbers::three); + REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); - constexpr auto dr = yae::enum_cast(119); - REQUIRE(yae::enum_cast(85).value() == Directions::Up); - REQUIRE(yae::enum_cast(-42).value() == Directions::Down); + constexpr auto dr = magic_enum::enum_cast(119); + REQUIRE(magic_enum::enum_cast(85).value() == Directions::Up); + REQUIRE(magic_enum::enum_cast(-42).value() == Directions::Down); REQUIRE(dr.value() == Directions::Right); - REQUIRE(yae::enum_cast(-119).value() == Directions::Left); - REQUIRE_FALSE(yae::enum_cast(0).has_value()); + REQUIRE(magic_enum::enum_cast(-119).value() == Directions::Left); + REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); - constexpr auto nt = yae::enum_cast(30); - REQUIRE(yae::enum_cast(10).value() == number::one); - REQUIRE(yae::enum_cast(20).value() == number::two); + constexpr auto nt = magic_enum::enum_cast(300); + REQUIRE(magic_enum::enum_cast(100).value() == number::one); + REQUIRE(magic_enum::enum_cast(200).value() == number::two); REQUIRE(nt.value() == number::three); - REQUIRE_FALSE(yae::enum_cast(0).has_value()); + REQUIRE_FALSE(magic_enum::enum_cast(0).has_value()); } } TEST_CASE("enum_value") { - constexpr auto cr = yae::enum_value(0); + constexpr auto cr = magic_enum::enum_value(0); REQUIRE(cr == Color::RED); - REQUIRE(yae::enum_value(1) == Color::GREEN); - REQUIRE(yae::enum_value(2) == Color::BLUE); + REQUIRE(magic_enum::enum_value(1) == Color::GREEN); + REQUIRE(magic_enum::enum_value(2) == Color::BLUE); - constexpr auto no = yae::enum_value(0); + constexpr auto no = magic_enum::enum_value(0); REQUIRE(no == Numbers::one); - REQUIRE(yae::enum_value(1) == Numbers::two); - REQUIRE(yae::enum_value(2) == Numbers::three); + REQUIRE(magic_enum::enum_value(1) == Numbers::two); + REQUIRE(magic_enum::enum_value(2) == Numbers::three); - constexpr auto dr = yae::enum_value(3); - REQUIRE(yae::enum_value(0) == Directions::Left); - REQUIRE(yae::enum_value(1) == Directions::Down); - REQUIRE(yae::enum_value(2) == Directions::Up); + constexpr auto dr = magic_enum::enum_value(3); + REQUIRE(magic_enum::enum_value(0) == Directions::Left); + REQUIRE(magic_enum::enum_value(1) == Directions::Down); + REQUIRE(magic_enum::enum_value(2) == Directions::Up); REQUIRE(dr == Directions::Right); - constexpr auto nt = yae::enum_value(2); - REQUIRE(yae::enum_value(0) == number::one); - REQUIRE(yae::enum_value(1) == number::two); + constexpr auto nt = magic_enum::enum_value(2); + REQUIRE(magic_enum::enum_value(0) == number::one); + REQUIRE(magic_enum::enum_value(1) == number::two); REQUIRE(nt == number::three); } TEST_CASE("enum_values") { - constexpr auto s1 = yae::enum_values(); + constexpr auto s1 = magic_enum::enum_values(); REQUIRE(s1 == std::array{{Color::RED, Color::GREEN, Color::BLUE}}); - constexpr auto s2 = yae::enum_values(); + constexpr auto s2 = magic_enum::enum_values(); REQUIRE(s2 == std::array{{Numbers::one, Numbers::two, Numbers::three}}); - constexpr auto s3 = yae::enum_values(); + constexpr auto s3 = magic_enum::enum_values(); REQUIRE(s3 == std::array{{Directions::Left, Directions::Down, Directions::Up, Directions::Right}}); - constexpr auto s4 = yae::enum_values(); + constexpr auto s4 = magic_enum::enum_values(); REQUIRE(s4 == std::array{{number::one, number::two, number::three}}); } TEST_CASE("enum_count") { - constexpr auto s1 = yae::enum_count(); + constexpr auto s1 = magic_enum::enum_count(); REQUIRE(s1 == 3); - constexpr auto s2 = yae::enum_count(); + constexpr auto s2 = magic_enum::enum_count(); REQUIRE(s2 == 3); - constexpr auto s3 = yae::enum_count(); + constexpr auto s3 = magic_enum::enum_count(); REQUIRE(s3 == 4); - constexpr auto s4 = yae::enum_count(); + constexpr auto s4 = magic_enum::enum_count(); REQUIRE(s4 == 3); } TEST_CASE("enum_name") { constexpr Color cr = Color::RED; - constexpr auto cr_name = yae::enum_name(cr); + constexpr auto cr_name = magic_enum::enum_name(cr); Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; REQUIRE(cr_name.value() == "RED"); - REQUIRE(yae::enum_name(Color::BLUE).value() == "BLUE"); - REQUIRE(yae::enum_name(cm[1]).value() == "GREEN"); - REQUIRE_FALSE(yae::enum_name(static_cast(MAGIC_ENUM_RANGE)).has_value()); - REQUIRE_FALSE(yae::enum_name(static_cast(-MAGIC_ENUM_RANGE)).has_value()); + REQUIRE(magic_enum::enum_name(Color::BLUE).value() == "BLUE"); + REQUIRE(magic_enum::enum_name(cm[1]).value() == "GREEN"); + REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); constexpr Numbers no = Numbers::one; - constexpr auto no_name = yae::enum_name(no); + constexpr auto no_name = magic_enum::enum_name(no); REQUIRE(no_name.value() == "one"); - REQUIRE(yae::enum_name(Numbers::two).value() == "two"); - REQUIRE(yae::enum_name(Numbers::three).value() == "three"); - REQUIRE_FALSE(yae::enum_name(static_cast(MAGIC_ENUM_RANGE)).has_value()); - REQUIRE_FALSE(yae::enum_name(static_cast(-MAGIC_ENUM_RANGE)).has_value()); + REQUIRE(magic_enum::enum_name(Numbers::two).value() == "two"); + REQUIRE(magic_enum::enum_name(Numbers::three).value() == "three"); + REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); constexpr Directions dr = Directions::Right; - constexpr auto dr_name = yae::enum_name(dr); - REQUIRE(yae::enum_name(Directions::Up).value() == "Up"); - REQUIRE(yae::enum_name(Directions::Down).value() == "Down"); + constexpr auto dr_name = magic_enum::enum_name(dr); + REQUIRE(magic_enum::enum_name(Directions::Up).value() == "Up"); + REQUIRE(magic_enum::enum_name(Directions::Down).value() == "Down"); REQUIRE(dr_name.value() == "Right"); - REQUIRE(yae::enum_name(Directions::Left).value() == "Left"); - REQUIRE_FALSE(yae::enum_name(static_cast(MAGIC_ENUM_RANGE)).has_value()); - REQUIRE_FALSE(yae::enum_name(static_cast(-MAGIC_ENUM_RANGE)).has_value()); + REQUIRE(magic_enum::enum_name(Directions::Left).value() == "Left"); + REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); constexpr number nt = number::three; - constexpr auto nt_name = yae::enum_name(nt); - REQUIRE(yae::enum_name(number::one).value() == "one"); - REQUIRE(yae::enum_name(number::two).value() == "two"); + constexpr auto nt_name = magic_enum::enum_name(nt); + REQUIRE(magic_enum::enum_name(number::one).value() == "one"); + REQUIRE(magic_enum::enum_name(number::two).value() == "two"); REQUIRE(nt_name.value() == "three"); - REQUIRE_FALSE(yae::enum_name(static_cast(MAGIC_ENUM_RANGE)).has_value()); - REQUIRE_FALSE(yae::enum_name(static_cast(-MAGIC_ENUM_RANGE)).has_value()); + REQUIRE_FALSE(magic_enum::enum_name(static_cast(0)).has_value()); } TEST_CASE("enum_names") { - constexpr auto s1 = yae::enum_names(); + constexpr auto s1 = magic_enum::enum_names(); REQUIRE(s1 == std::array{{"RED", "GREEN", "BLUE"}}); - constexpr auto s2 = yae::enum_names(); + constexpr auto s2 = magic_enum::enum_names(); REQUIRE(s2 == std::array{{"one", "two", "three"}}); - constexpr auto s3 = yae::enum_names(); + constexpr auto s3 = magic_enum::enum_names(); REQUIRE(s3 == std::array{{"Left", "Down", "Up", "Right"}}); - constexpr auto s4 = yae::enum_names(); + constexpr auto s4 = magic_enum::enum_names(); REQUIRE(s4 == std::array{{"one", "two", "three"}}); } TEST_CASE("operator<<") { auto test_ostream = [](auto e, std::string_view name) { - using namespace yae::ops; + using namespace magic_enum::ops; std::stringstream ss; ss << e; REQUIRE(ss.str() == name);