// Licensed under the MIT License . // SPDX-License-Identifier: MIT // Copyright (c) 2019 - 2024 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. #define CATCH_CONFIG_MAIN #include #define MAGIC_ENUM_NO_CHECK_REFLECTED_ENUM #define MAGIC_ENUM_RANGE_MIN -120 #define MAGIC_ENUM_RANGE_MAX 120 #include #include #include #include #include #include #include #include enum class Color { RED = -12, GREEN = 7, BLUE = 15 }; template <> constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name(Color value) noexcept { switch (value) { case Color::RED: return "red"; default: return default_tag; } } enum class Numbers : int { one = 1, two, three, many = 127 }; enum Directions { Up = 85, Down = -42, Right = 120, Left = -120 }; enum number : unsigned long { one = 100, two = 200, three = 300, four = 400, #if defined(MAGIC_ENUM_SUPPORTED_ALIASES) _1 = one, _2 = two, _3 = three, _4 = four #endif }; template <> struct magic_enum::customize::enum_range { static constexpr int min = 100; static constexpr int max = 300; }; enum class crc_hack { b5a7b602ab754d7ab30fb42c4fb28d82 }; enum class crc_hack_2 { b5a7b602ab754d7ab30fb42c4fb28d82, d19f2e9e82d14b96be4fa12b8a27ee9f }; enum class MaxUsedAsInvalid : std::uint8_t { ONE, TWO = 63, INVALID = std::numeric_limits::max() }; template <> struct magic_enum::customize::enum_range { static constexpr int min = 0; static constexpr int max = 64; }; enum class Binary : bool { ONE, TWO }; template <> struct magic_enum::customize::enum_range { static constexpr int min = 0; static constexpr int max = 64; }; enum class BoolTest : bool { Yay, Nay }; using namespace magic_enum; static_assert(is_magic_enum_supported, "magic_enum: Unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility)."); TEST_CASE("enum_cast") { SECTION("string") { constexpr auto cr = enum_cast("red"); REQUIRE(cr.value() == Color::RED); REQUIRE(enum_cast("GREEN").value() == Color::GREEN); REQUIRE(enum_cast("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }).value() == Color::BLUE); REQUIRE_FALSE(enum_cast("None").has_value()); constexpr auto no = enum_cast("one"); REQUIRE(no.value() == Numbers::one); REQUIRE(enum_cast("two").value() == Numbers::two); REQUIRE(enum_cast("three").value() == Numbers::three); REQUIRE_FALSE(enum_cast("many").has_value()); REQUIRE_FALSE(enum_cast("None").has_value()); constexpr auto dr = enum_cast("Right"); REQUIRE(enum_cast("Up").value() == Directions::Up); REQUIRE(enum_cast("Down").value() == Directions::Down); REQUIRE(dr.value() == Directions::Right); REQUIRE(enum_cast("Left").value() == Directions::Left); REQUIRE_FALSE(enum_cast("None").has_value()); constexpr auto dr2 = enum_cast("RIGHT", case_insensitive); REQUIRE(dr2.value() == Directions::Right); REQUIRE(enum_cast("up", case_insensitive).value() == Directions::Up); REQUIRE(enum_cast("dOwN", case_insensitive).value() == Directions::Down); REQUIRE_FALSE(enum_cast("Left-", case_insensitive).has_value()); constexpr auto nt = enum_cast("three"); REQUIRE(enum_cast("one").value() == number::one); REQUIRE(enum_cast("two").value() == number::two); REQUIRE(nt.value() == number::three); REQUIRE_FALSE(enum_cast("four").has_value()); REQUIRE_FALSE(enum_cast("None").has_value()); REQUIRE(enum_cast("b5a7b602ab754d7ab30fb42c4fb28d82").has_value()); REQUIRE_FALSE(enum_cast("d19f2e9e82d14b96be4fa12b8a27ee9f").has_value()); constexpr auto crc = enum_cast("b5a7b602ab754d7ab30fb42c4fb28d82"); REQUIRE(crc.value() == crc_hack_2::b5a7b602ab754d7ab30fb42c4fb28d82); REQUIRE(enum_cast("d19f2e9e82d14b96be4fa12b8a27ee9f").value() == crc_hack_2::d19f2e9e82d14b96be4fa12b8a27ee9f); REQUIRE(enum_cast("Nay").has_value()); } SECTION("integer") { Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; constexpr auto cr = enum_cast(-12); REQUIRE(cr.value() == Color::RED); REQUIRE(enum_cast(7).value() == Color::GREEN); REQUIRE(enum_cast(static_cast(cm[2])).value() == Color::BLUE); REQUIRE_FALSE(enum_cast(0).has_value()); constexpr auto no = enum_cast(1); REQUIRE(no.value() == Numbers::one); REQUIRE(enum_cast(2).value() == Numbers::two); REQUIRE(enum_cast(3).value() == Numbers::three); REQUIRE_FALSE(enum_cast(127).has_value()); REQUIRE_FALSE(enum_cast(0).has_value()); constexpr auto dr = enum_cast(120); REQUIRE(enum_cast(85).value() == Directions::Up); REQUIRE(enum_cast(-42).value() == Directions::Down); REQUIRE(dr.value() == Directions::Right); REQUIRE(enum_cast(-120).value() == Directions::Left); REQUIRE_FALSE(enum_cast(0).has_value()); constexpr auto nt = enum_cast(300); REQUIRE(enum_cast(100).value() == number::one); REQUIRE(enum_cast(200).value() == number::two); REQUIRE(nt.value() == number::three); REQUIRE_FALSE(enum_cast(400).has_value()); REQUIRE_FALSE(enum_cast(0).has_value()); REQUIRE(enum_cast(false).has_value()); REQUIRE(enum_cast(0).has_value()); } } TEST_CASE("enum_integer") { Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; constexpr auto cr = enum_integer(Color::RED); Color cg = Color::GREEN; REQUIRE(cr == -12); REQUIRE(enum_integer(cg) == 7); REQUIRE(enum_integer(cm[2]) == 15); REQUIRE(enum_integer(static_cast(0)) == 0); constexpr auto no = enum_integer(Numbers::one); REQUIRE(no == 1); REQUIRE(enum_integer(Numbers::two) == 2); REQUIRE(enum_integer(Numbers::three) == 3); REQUIRE(enum_integer(Numbers::many) == 127); REQUIRE(enum_integer(static_cast(0)) == 0); constexpr auto dr = enum_integer(Directions::Right); Directions dl = Directions::Left; REQUIRE(enum_integer(dl) == -120); REQUIRE(enum_integer(Directions::Down) == -42); REQUIRE(enum_integer(Directions::Up) == 85); REQUIRE(dr == 120); REQUIRE(enum_integer(static_cast(0)) == 0); constexpr auto nt = enum_integer(number::three); REQUIRE(enum_integer(number::one) == 100); REQUIRE(enum_integer(number::two) == 200); REQUIRE(nt == 300); REQUIRE(enum_integer(number::four) == 400); REQUIRE(enum_integer(static_cast(0)) == 0); REQUIRE(enum_integer(BoolTest::Yay) == false); } TEST_CASE("enum_index") { Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; constexpr auto cr = enum_index(Color::RED); Color cg = Color::GREEN; REQUIRE(cr.value() == 0); REQUIRE(enum_index() == 0); REQUIRE(enum_index(cg).value() == 1); REQUIRE(enum_index(cm[2]).value() == 2); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); constexpr auto no = enum_index(Numbers::one); REQUIRE(no.value() == 0); REQUIRE(enum_index() == 0); REQUIRE(enum_index(Numbers::two).value() == 1); REQUIRE(enum_index(Numbers::three).value() == 2); REQUIRE_FALSE(enum_index(Numbers::many).has_value()); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); constexpr auto dr = enum_index(Directions::Right); Directions dl = Directions::Left; REQUIRE(enum_index() == 0); REQUIRE(enum_index(dl).value() == 0); REQUIRE(enum_index(Directions::Down).value() == 1); REQUIRE(enum_index(Directions::Up).value() == 2); REQUIRE(dr.value() == 3); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); constexpr auto nt = enum_index(number::three); REQUIRE(enum_index() == 0); REQUIRE(enum_index(number::one).value() == 0); REQUIRE(enum_index(number::two).value() == 1); REQUIRE(nt.value() == 2); REQUIRE_FALSE(enum_index(number::four).has_value()); REQUIRE_FALSE(enum_index(static_cast(0)).has_value()); REQUIRE(enum_index() == 0); } TEST_CASE("enum_contains") { SECTION("value") { Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; constexpr auto cr = enum_contains(Color::RED); Color cg = Color::GREEN; REQUIRE(cr); REQUIRE(enum_contains(cg)); REQUIRE(enum_contains(cm[2])); REQUIRE_FALSE(enum_contains(static_cast(0))); constexpr auto no = enum_contains(Numbers::one); REQUIRE(no); REQUIRE(enum_contains(Numbers::two)); REQUIRE(enum_contains(Numbers::three)); REQUIRE_FALSE(enum_contains(Numbers::many)); REQUIRE_FALSE(enum_contains(static_cast(0))); constexpr auto dr = enum_contains(Directions::Right); Directions dl = Directions::Left; REQUIRE(enum_contains(dl)); REQUIRE(enum_contains(Directions::Down)); REQUIRE(enum_contains(Directions::Up)); REQUIRE(dr); REQUIRE_FALSE(enum_contains(static_cast(0))); constexpr auto nt = enum_contains(number::three); REQUIRE(enum_contains(number::one)); REQUIRE(enum_contains(number::two)); REQUIRE(nt); REQUIRE_FALSE(enum_contains(number::four)); REQUIRE_FALSE(enum_contains(static_cast(0))); REQUIRE(enum_contains(BoolTest::Yay)); } SECTION("integer") { REQUIRE(enum_contains(-12)); REQUIRE(enum_contains(7)); REQUIRE(enum_contains(15)); REQUIRE_FALSE(enum_contains(42)); REQUIRE_FALSE(enum_contains(-120)); REQUIRE_FALSE(enum_contains(0)); constexpr auto no = enum_integer(Numbers::one); REQUIRE(enum_contains(no)); REQUIRE(enum_contains(enum_integer(Numbers::two))); REQUIRE(enum_contains(enum_integer(Numbers::three))); REQUIRE_FALSE(enum_contains(enum_integer(Numbers::many))); constexpr auto dr = enum_integer(Directions::Right); REQUIRE(enum_contains(dr)); REQUIRE(enum_contains(Directions::Down)); REQUIRE(enum_contains(Directions::Up)); REQUIRE_FALSE(enum_contains(static_cast(0))); constexpr auto nt = enum_contains(number::three); REQUIRE(enum_contains(number::one)); REQUIRE(enum_contains(100)); REQUIRE(enum_contains(200)); REQUIRE(enum_contains(300)); REQUIRE(enum_contains(number::two)); REQUIRE(nt); REQUIRE_FALSE(enum_contains(number::four)); REQUIRE_FALSE(enum_contains(111)); REQUIRE_FALSE(enum_contains(0)); REQUIRE(enum_contains(false)); REQUIRE(enum_contains(0)); } SECTION("string") { constexpr auto cr = "red"; REQUIRE(enum_contains(cr)); REQUIRE(enum_contains("GREEN")); REQUIRE(enum_contains("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); })); REQUIRE_FALSE(enum_contains("None")); constexpr auto no = std::string_view{"one"}; REQUIRE(enum_contains(no)); REQUIRE(enum_contains("two")); REQUIRE(enum_contains("three")); REQUIRE_FALSE(enum_contains("many")); REQUIRE_FALSE(enum_contains("None")); auto dr = std::string{"Right"}; REQUIRE(enum_contains("Up")); REQUIRE(enum_contains("Down")); REQUIRE(enum_contains(dr)); REQUIRE(enum_contains("Left")); REQUIRE_FALSE(enum_contains("None")); auto dr2 = std::string{"RIGHT"}; REQUIRE(enum_contains(dr2, case_insensitive)); REQUIRE(enum_contains("up", case_insensitive)); REQUIRE(enum_contains("dOwN", case_insensitive)); REQUIRE_FALSE(enum_contains("Left-", case_insensitive)); constexpr auto nt = enum_contains("three"); REQUIRE(enum_contains("one")); REQUIRE(enum_contains("two")); REQUIRE(nt); REQUIRE_FALSE(enum_contains("four")); REQUIRE_FALSE(enum_contains("None")); REQUIRE(enum_contains("Yay")); } } TEST_CASE("enum_value") { constexpr auto cr = enum_value(0); REQUIRE(cr == Color::RED); REQUIRE(enum_value(1) == Color::GREEN); REQUIRE(enum_value(2) == Color::BLUE); REQUIRE(enum_value() == Color::RED); REQUIRE(enum_value() == Color::GREEN); REQUIRE(enum_value() == Color::BLUE); constexpr auto no = enum_value(0); REQUIRE(no == Numbers::one); REQUIRE(enum_value(1) == Numbers::two); REQUIRE(enum_value(2) == Numbers::three); REQUIRE(enum_value() == Numbers::one); REQUIRE(enum_value() == Numbers::two); REQUIRE(enum_value() == Numbers::three); constexpr auto dr = enum_value(3); REQUIRE(enum_value(0) == Directions::Left); REQUIRE(enum_value(1) == Directions::Down); REQUIRE(enum_value(2) == Directions::Up); REQUIRE(dr == Directions::Right); REQUIRE(enum_value() == Directions::Left); REQUIRE(enum_value() == Directions::Down); REQUIRE(enum_value() == Directions::Up); REQUIRE(enum_value() == Directions::Right); constexpr auto nt = enum_value(2); REQUIRE(enum_value(0) == number::one); REQUIRE(enum_value(1) == number::two); REQUIRE(nt == number::three); REQUIRE(enum_value() == number::one); REQUIRE(enum_value() == number::two); REQUIRE(enum_value() == number::three); REQUIRE(enum_value(0) == BoolTest::Yay); REQUIRE(enum_value() == BoolTest::Yay); } TEST_CASE("enum_values") { REQUIRE(std::is_same_v()), const std::array&>); constexpr auto& s1 = enum_values(); REQUIRE(s1 == std::array{{Color::RED, Color::GREEN, Color::BLUE}}); constexpr auto& s2 = enum_values(); REQUIRE(s2 == std::array{{Numbers::one, Numbers::two, Numbers::three}}); constexpr auto& s3 = enum_values(); REQUIRE(s3 == std::array{{Directions::Left, Directions::Down, Directions::Up, Directions::Right}}); constexpr auto& s4 = enum_values(); REQUIRE(s4 == std::array{{number::one, number::two, number::three}}); constexpr auto& s5 = enum_values(); REQUIRE(s5 == std::array{{Binary::ONE, Binary::TWO}}); constexpr auto& s6 = enum_values(); REQUIRE(s6 == std::array{{MaxUsedAsInvalid::ONE, MaxUsedAsInvalid::TWO}}); } TEST_CASE("enum_count") { constexpr auto s1 = enum_count(); REQUIRE(s1 == 3); constexpr auto s2 = enum_count(); REQUIRE(s2 == 3); constexpr auto s3 = enum_count(); REQUIRE(s3 == 4); constexpr auto s4 = enum_count(); REQUIRE(s4 == 3); constexpr auto s5 = enum_count(); REQUIRE(s5 == 2); constexpr auto s6 = enum_count(); REQUIRE(s6 == 2); } enum lt1 { s1, loooooooooooooooooooong1 }; enum lt2 : unsigned { s2, loooooooooooooooooooong2 }; enum class lt3 { s3, loooooooooooooooooooong3 }; enum class lt4 : unsigned { s4, loooooooooooooooooooong4 }; class foo1 { public: enum class lt5 { s5, loooooooooooooooooooong5 }; }; class foo2 { public: enum lt6 { s6, loooooooooooooooooooong6 }; }; namespace boo1 { enum lt1 { s1, loooooooooooooooooooong1 }; enum lt2 : unsigned { s2, loooooooooooooooooooong2 }; enum class lt3 { s3, loooooooooooooooooooong3 }; enum class lt4 : unsigned { s4, loooooooooooooooooooong4 }; class foo1 { public: enum class lt5 { s5, loooooooooooooooooooong5 }; }; class foo2 { public: enum lt6 { s6, loooooooooooooooooooong6 }; }; } // namespace boo1 namespace boo2 { namespace boo3 { enum lt1 { s1, loooooooooooooooooooong1 }; enum lt2 : unsigned { s2, loooooooooooooooooooong2 }; enum class lt3 { s3, loooooooooooooooooooong3 }; enum class lt4 : unsigned { s4, loooooooooooooooooooong4 }; class foo1 { public: enum class lt5 { s5, loooooooooooooooooooong5 }; }; class foo2 { public: enum lt6 { s6, loooooooooooooooooooong6 }; }; } // namespace boo2::boo3 } // namespace boo2 namespace { enum a_lt1 { s1, loooooooooooooooooooong1 }; enum a_lt2 : unsigned { s2, loooooooooooooooooooong2 }; enum class a_lt3 { s3, loooooooooooooooooooong3 }; enum class a_lt4 : unsigned { s4, loooooooooooooooooooong4 }; class a_foo1 { public: enum class a_lt5 { s5, loooooooooooooooooooong5 }; }; class a_foo2 { public: enum a_lt6 { s6, loooooooooooooooooooong6 }; }; } // namespace enum class LargeNumbers { First = -1024, Second = 1024 }; TEST_CASE("enum_name") { SECTION("automatic storage") { constexpr Color cr = Color::RED; constexpr auto cr_name = enum_name(cr); Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; Color cb = Color::BLUE; REQUIRE(cr_name == "red"); REQUIRE(enum_name(cb) == "BLUE"); REQUIRE(enum_name>(cm[1]) == "GREEN"); REQUIRE(enum_name>(cm[1]) == "GREEN"); REQUIRE(enum_name>(static_cast(0)).empty()); constexpr Numbers no = Numbers::one; constexpr auto no_name = enum_name(no); REQUIRE(no_name == "one"); REQUIRE(enum_name>(Numbers::two) == "two"); REQUIRE(enum_name, Numbers>(Numbers::three) == "three"); REQUIRE(enum_name(Numbers::many).empty()); REQUIRE(enum_name(static_cast(0)).empty()); constexpr Directions dr = Directions::Right; constexpr auto dr_name = enum_name(dr); Directions du = Directions::Up; REQUIRE(enum_name(du) == "Up"); REQUIRE(enum_name(Directions::Down) == "Down"); REQUIRE(dr_name == "Right"); REQUIRE(enum_name(Directions::Left) == "Left"); REQUIRE(enum_name(static_cast(0)).empty()); constexpr number nt = number::three; constexpr auto nt_name = enum_name(nt); REQUIRE(enum_name(number::one) == "one"); REQUIRE(enum_name(number::two) == "two"); REQUIRE(nt_name == "three"); REQUIRE(enum_name(number::four).empty()); REQUIRE(enum_name(static_cast(0)).empty()); REQUIRE(enum_name(MaxUsedAsInvalid::ONE) == "ONE"); REQUIRE(enum_name(lt1::s1) == "s1"); REQUIRE(enum_name(lt1::loooooooooooooooooooong1) == "loooooooooooooooooooong1"); REQUIRE(enum_name(lt2::s2) == "s2"); REQUIRE(enum_name(lt2::loooooooooooooooooooong2) == "loooooooooooooooooooong2"); REQUIRE(enum_name(lt3::s3) == "s3"); REQUIRE(enum_name(lt3::loooooooooooooooooooong3) == "loooooooooooooooooooong3"); REQUIRE(enum_name(lt4::s4) == "s4"); REQUIRE(enum_name(lt4::loooooooooooooooooooong4) == "loooooooooooooooooooong4"); REQUIRE(enum_name(foo1::lt5::s5) == "s5"); REQUIRE(enum_name(foo1::lt5::loooooooooooooooooooong5) == "loooooooooooooooooooong5"); REQUIRE(enum_name(foo2::s6) == "s6"); REQUIRE(enum_name(foo2::loooooooooooooooooooong6) == "loooooooooooooooooooong6"); REQUIRE_FALSE(enum_name((foo1::lt5)12).size()); REQUIRE_FALSE(enum_name((foo2::lt6)12).size()); REQUIRE(enum_name(boo1::lt1::s1) == "s1"); REQUIRE(enum_name(boo1::lt1::loooooooooooooooooooong1) == "loooooooooooooooooooong1"); REQUIRE(enum_name(boo1::lt2::s2) == "s2"); REQUIRE(enum_name(boo1::lt2::loooooooooooooooooooong2) == "loooooooooooooooooooong2"); REQUIRE(enum_name(boo1::lt3::s3) == "s3"); REQUIRE(enum_name(boo1::lt3::loooooooooooooooooooong3) == "loooooooooooooooooooong3"); REQUIRE(enum_name(boo1::lt4::s4) == "s4"); REQUIRE(enum_name(boo1::lt4::loooooooooooooooooooong4) == "loooooooooooooooooooong4"); REQUIRE(enum_name(boo1::foo1::lt5::s5) == "s5"); REQUIRE(enum_name(boo1::foo1::lt5::loooooooooooooooooooong5) == "loooooooooooooooooooong5"); REQUIRE(enum_name(boo1::foo2::s6) == "s6"); REQUIRE(enum_name(boo1::foo2::loooooooooooooooooooong6) == "loooooooooooooooooooong6"); REQUIRE_FALSE(enum_name((boo1::foo1::lt5)12).size()); REQUIRE_FALSE(enum_name((boo1::foo2::lt6)12).size()); REQUIRE(enum_name(boo2::boo3::lt1::s1) == "s1"); REQUIRE(enum_name(boo2::boo3::lt1::loooooooooooooooooooong1) == "loooooooooooooooooooong1"); REQUIRE(enum_name(boo2::boo3::lt2::s2) == "s2"); REQUIRE(enum_name(boo2::boo3::lt2::loooooooooooooooooooong2) == "loooooooooooooooooooong2"); REQUIRE(enum_name(boo2::boo3::lt3::s3) == "s3"); REQUIRE(enum_name(boo2::boo3::lt3::loooooooooooooooooooong3) == "loooooooooooooooooooong3"); REQUIRE(enum_name(boo2::boo3::lt4::s4) == "s4"); REQUIRE(enum_name(boo2::boo3::lt4::loooooooooooooooooooong4) == "loooooooooooooooooooong4"); REQUIRE(enum_name(boo2::boo3::foo1::lt5::s5) == "s5"); REQUIRE(enum_name(boo2::boo3::foo1::lt5::loooooooooooooooooooong5) == "loooooooooooooooooooong5"); REQUIRE(enum_name(boo2::boo3::foo2::s6) == "s6"); REQUIRE(enum_name(boo2::boo3::foo2::loooooooooooooooooooong6) == "loooooooooooooooooooong6"); REQUIRE_FALSE(enum_name((boo2::boo3::foo1::lt5)12).size()); REQUIRE_FALSE(enum_name((boo2::boo3::foo2::lt6)12).size()); REQUIRE(enum_name(a_lt1::s1) == "s1"); REQUIRE(enum_name(a_lt1::loooooooooooooooooooong1) == "loooooooooooooooooooong1"); REQUIRE(enum_name(a_lt2::s2) == "s2"); REQUIRE(enum_name(a_lt2::loooooooooooooooooooong2) == "loooooooooooooooooooong2"); REQUIRE(enum_name(a_lt3::s3) == "s3"); REQUIRE(enum_name(a_lt3::loooooooooooooooooooong3) == "loooooooooooooooooooong3"); REQUIRE(enum_name(a_lt4::s4) == "s4"); REQUIRE(enum_name(a_lt4::loooooooooooooooooooong4) == "loooooooooooooooooooong4"); REQUIRE(enum_name(a_foo1::a_lt5::s5) == "s5"); REQUIRE(enum_name(a_foo1::a_lt5::loooooooooooooooooooong5) == "loooooooooooooooooooong5"); REQUIRE(enum_name(a_foo2::s6) == "s6"); REQUIRE(enum_name(a_foo2::loooooooooooooooooooong6) == "loooooooooooooooooooong6"); REQUIRE_FALSE(enum_name((a_foo1::a_lt5)12).size()); REQUIRE_FALSE(enum_name((a_foo2::a_lt6)12).size()); } SECTION("static storage") { constexpr Color cr = Color::RED; constexpr auto cr_name = enum_name(); constexpr Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE}; REQUIRE(cr_name == "red"); REQUIRE(enum_name() == "BLUE"); REQUIRE(enum_name() == "GREEN"); constexpr Numbers no = Numbers::one; constexpr auto no_name = enum_name(); REQUIRE(no_name == "one"); REQUIRE(enum_name() == "two"); REQUIRE(enum_name() == "three"); REQUIRE(enum_name() == "many"); constexpr Directions dr = Directions::Right; constexpr auto dr_name = enum_name(); REQUIRE(enum_name() == "Up"); REQUIRE(enum_name() == "Down"); REQUIRE(dr_name == "Right"); REQUIRE(enum_name() == "Left"); constexpr number nt = number::three; constexpr auto nt_name = enum_name(); REQUIRE(enum_name() == "one"); REQUIRE(enum_name() == "two"); REQUIRE(nt_name == "three"); REQUIRE(enum_name() == "four"); REQUIRE(enum_name() == "ONE"); REQUIRE(enum_name() == "ONE"); } SECTION("empty if the value is out of range") { const auto ln_value = GENERATE(LargeNumbers::First, LargeNumbers::Second); const auto ln_name = enum_name(ln_value); REQUIRE(ln_name.empty()); } } TEST_CASE("enum_names") { REQUIRE(std::is_same_v()), const std::array&>); constexpr auto& s1 = enum_names(); REQUIRE(s1 == std::array{{"red", "GREEN", "BLUE"}}); constexpr auto& s2 = enum_names(); REQUIRE(s2 == std::array{{"one", "two", "three"}}); constexpr auto& s3 = enum_names(); REQUIRE(s3 == std::array{{"Left", "Down", "Up", "Right"}}); constexpr auto& s4 = enum_names(); REQUIRE(s4 == std::array{{"one", "two", "three"}}); } TEST_CASE("enum_entries") { REQUIRE(std::is_same_v()), const std::array, 3>&>); constexpr auto& s1 = enum_entries(); REQUIRE(s1 == std::array, 3>{{{Color::RED, "red"}, {Color::GREEN, "GREEN"}, {Color::BLUE, "BLUE"}}}); constexpr auto& s2 = enum_entries(); REQUIRE(s2 == std::array, 3>{{{Numbers::one, "one"}, {Numbers::two, "two"}, {Numbers::three, "three"}}}); constexpr auto& s3 = enum_entries(); REQUIRE(s3 == std::array, 4>{{{Directions::Left, "Left"}, {Directions::Down, "Down"}, {Directions::Up, "Up"}, {Directions::Right, "Right"}}}); constexpr auto& s4 = enum_entries(); REQUIRE(s4 == std::array, 3>{{{number::one, "one"}, {number::two, "two"}, {number::three, "three"}}}); } TEST_CASE("ostream_operators") { auto test_ostream = [](auto e, std::string name) { using namespace magic_enum::ostream_operators; std::stringstream ss; ss << e; REQUIRE(ss); REQUIRE(ss.str() == name); }; test_ostream(std::make_optional(Color::RED), "red"); test_ostream(Color::GREEN, "GREEN"); test_ostream(Color::BLUE, "BLUE"); test_ostream(static_cast(0), "0"); test_ostream(std::make_optional(static_cast(0)), "0"); test_ostream(std::make_optional(Numbers::one), "one"); test_ostream(Numbers::two, "two"); test_ostream(Numbers::three, "three"); test_ostream(Numbers::many, "127"); test_ostream(static_cast(0), "0"); test_ostream(std::make_optional(static_cast(0)), "0"); test_ostream(std::make_optional(Directions::Up), "Up"); test_ostream(Directions::Down, "Down"); test_ostream(Directions::Right, "Right"); test_ostream(Directions::Left, "Left"); test_ostream(static_cast(0), "0"); test_ostream(std::make_optional(static_cast(0)), "0"); test_ostream(std::make_optional(number::one), "one"); test_ostream(number::two, "two"); test_ostream(number::three, "three"); test_ostream(number::four, "400"); test_ostream(static_cast(0), "0"); test_ostream(std::make_optional(static_cast(0)), "0"); } TEST_CASE("istream_operators") { auto test_istream = [](const auto e, std::string name) { using namespace magic_enum::istream_operators; std::istringstream ss(name); std::decay_t v; ss >> v; REQUIRE(ss); REQUIRE(v == e); }; test_istream(Color::GREEN, "GREEN"); test_istream(Color::BLUE, "BLUE"); test_istream(Numbers::two, "two"); test_istream(Numbers::three, "three"); test_istream(Directions::Down, "Down"); test_istream(Directions::Right, "Right"); test_istream(Directions::Left, "Left"); test_istream(number::two, "two"); test_istream(number::three, "three"); } TEST_CASE("bitwise_operators") { using namespace magic_enum::bitwise_operators; SECTION("operator^") { REQUIRE(enum_integer(~Color::RED) == ~enum_integer(Color::RED)); REQUIRE(enum_integer(~Numbers::one) == ~enum_integer(Numbers::one)); REQUIRE(enum_integer(~Directions::Up) == ~enum_integer(Directions::Up)); REQUIRE(enum_integer(~number::one) == ~enum_integer(number::one)); } SECTION("operator|") { REQUIRE(enum_integer(Color::RED | Color::BLUE) == (enum_integer(Color::RED) | enum_integer(Color::BLUE))); REQUIRE(enum_integer(Numbers::one | Numbers::two) == (enum_integer(Numbers::one) | enum_integer(Numbers::two))); REQUIRE(enum_integer(Directions::Up | Directions::Down) == (enum_integer(Directions::Up) | enum_integer(Directions::Down))); REQUIRE(enum_integer(number::one | number::two) == (enum_integer(number::one) | enum_integer(number::two))); } SECTION("operator&") { REQUIRE(enum_integer(Color::RED & Color::BLUE) == (enum_integer(Color::RED) & enum_integer(Color::BLUE))); REQUIRE(enum_integer(Numbers::one & Numbers::two) == (enum_integer(Numbers::one) & enum_integer(Numbers::two))); REQUIRE(enum_integer(Directions::Up & Directions::Down) == (enum_integer(Directions::Up) & enum_integer(Directions::Down))); REQUIRE(enum_integer(number::one & number::two) == (enum_integer(number::one) & enum_integer(number::two))); } SECTION("operator^") { REQUIRE(enum_integer(Color::RED ^ Color::BLUE) == (enum_integer(Color::RED) ^ enum_integer(Color::BLUE))); REQUIRE(enum_integer(Numbers::one ^ Numbers::two) == (enum_integer(Numbers::one) ^ enum_integer(Numbers::two))); REQUIRE(enum_integer(Directions::Up ^ Directions::Down) == (enum_integer(Directions::Up) ^ enum_integer(Directions::Down))); REQUIRE(enum_integer(number::one ^ number::two) == (enum_integer(number::one) ^ enum_integer(number::two))); } SECTION("operator|=") { Color x1 = Color::RED; x1 |= Color::BLUE; REQUIRE(enum_integer(x1) == (enum_integer(Color::RED) | enum_integer(Color::BLUE))); Numbers x2 = Numbers::one; x2 |= Numbers::two; REQUIRE(enum_integer(x2) == (enum_integer(Numbers::one) | enum_integer(Numbers::two))); Directions x3 = Directions::Up; x3 |= Directions::Down; REQUIRE(enum_integer(x3) == (enum_integer(Directions::Up) | enum_integer(Directions::Down))); number x4 = number::one; x4 |= number::two; REQUIRE(enum_integer(x4) == (enum_integer(number::one) | enum_integer(number::two))); } SECTION("operator&=") { Color x1 = Color::RED; x1 &= Color::BLUE; REQUIRE(enum_integer(x1) == (enum_integer(Color::RED) & enum_integer(Color::BLUE))); Numbers x2 = Numbers::one; x2 &= Numbers::two; REQUIRE(enum_integer(x2) == (enum_integer(Numbers::one) & enum_integer(Numbers::two))); Directions x3 = Directions::Up; x3 &= Directions::Down; REQUIRE(enum_integer(x3) == (enum_integer(Directions::Up) & enum_integer(Directions::Down))); number x4 = number::one; x4 &= number::two; REQUIRE(enum_integer(x4) == (enum_integer(number::one) & enum_integer(number::two))); } SECTION("operator^=") { Color x1 = Color::RED; x1 ^= Color::BLUE; REQUIRE(enum_integer(x1) == (enum_integer(Color::RED) ^ enum_integer(Color::BLUE))); Numbers x2 = Numbers::one; x2 ^= Numbers::two; REQUIRE(enum_integer(x2) == (enum_integer(Numbers::one) ^ enum_integer(Numbers::two))); Directions x3 = Directions::Up; x3 ^= Directions::Down; REQUIRE(enum_integer(x3) == (enum_integer(Directions::Up) ^ enum_integer(Directions::Down))); number x4 = number::one; x4 ^= number::two; REQUIRE(enum_integer(x4) == (enum_integer(number::one) ^ enum_integer(number::two))); } } TEST_CASE("type_traits") { REQUIRE_FALSE(is_unscoped_enum_v); REQUIRE_FALSE(is_unscoped_enum_v); REQUIRE(is_unscoped_enum_v); REQUIRE(is_unscoped_enum_v); REQUIRE(is_scoped_enum_v); REQUIRE(is_scoped_enum_v); REQUIRE_FALSE(is_scoped_enum_v); REQUIRE_FALSE(is_scoped_enum_v); } TEST_CASE("enum_type_name") { REQUIRE(enum_type_name() == "Color"); REQUIRE(enum_type_name() == "Numbers"); REQUIRE(enum_type_name() == "Directions"); REQUIRE(enum_type_name() == "number"); REQUIRE(enum_type_name() == "lt1"); REQUIRE(enum_type_name() == "lt2"); REQUIRE(enum_type_name() == "lt3"); REQUIRE(enum_type_name() == "lt4"); REQUIRE(enum_type_name() == "lt5"); REQUIRE(enum_type_name() == "lt6"); REQUIRE(enum_type_name() == "lt6"); REQUIRE(enum_type_name() == "lt1"); REQUIRE(enum_type_name() == "lt2"); REQUIRE(enum_type_name() == "lt3"); REQUIRE(enum_type_name() == "lt4"); REQUIRE(enum_type_name() == "lt5"); REQUIRE(enum_type_name() == "lt6"); REQUIRE(enum_type_name() == "lt6"); REQUIRE(enum_type_name() == "lt1"); REQUIRE(enum_type_name() == "lt2"); REQUIRE(enum_type_name() == "lt3"); REQUIRE(enum_type_name() == "lt4"); REQUIRE(enum_type_name() == "lt5"); REQUIRE(enum_type_name() == "lt6"); REQUIRE(enum_type_name() == "lt6"); REQUIRE(enum_type_name() == "a_lt1"); REQUIRE(enum_type_name() == "a_lt2"); REQUIRE(enum_type_name() == "a_lt3"); REQUIRE(enum_type_name() == "a_lt4"); REQUIRE(enum_type_name() == "a_lt5"); REQUIRE(enum_type_name() == "a_lt6"); REQUIRE(enum_type_name() == "a_lt6"); } #if defined(MAGIC_ENUM_SUPPORTED_ALIASES) TEST_CASE("aliases") { REQUIRE(enum_count() == 3); REQUIRE(enum_name(number::one) == enum_name(number::_1)); REQUIRE(enum_name(number::two) == enum_name(number::_2)); REQUIRE(enum_name(number::three) == enum_name(number::_3)); REQUIRE(enum_name(number::four) == enum_name(number::_4)); REQUIRE(enum_integer(number::one) == enum_integer(number::_1)); REQUIRE(enum_integer(number::two) == enum_integer(number::_2)); REQUIRE(enum_integer(number::three) == enum_integer(number::_3)); REQUIRE(enum_integer(number::four) == enum_integer(number::_4)); REQUIRE_FALSE(enum_cast("_1").has_value()); REQUIRE_FALSE(enum_cast("_2").has_value()); REQUIRE_FALSE(enum_cast("_3").has_value()); REQUIRE_FALSE(enum_cast("_4").has_value()); } #endif TEST_CASE("extrema") { enum class BadColor : std::uint64_t { RED, GREEN, YELLOW, // The value NONE is ignored (out of range). // However, it affects the value of min_v. When reflected_min_v was incorrect, // the presence of NONE caused miv_v to be equal to -1, which was then cast to unsigned, // leading to a value of 18446744073709551615 (numeric_limit_max of uint64_t). NONE = std::numeric_limits::max() }; REQUIRE(magic_enum::enum_name(BadColor::NONE).empty()); REQUIRE_FALSE(enum_cast(std::numeric_limits::max()).has_value()); REQUIRE_FALSE(magic_enum::enum_contains(std::numeric_limits::max())); REQUIRE_FALSE(magic_enum::enum_contains(BadColor::NONE)); SECTION("min") { REQUIRE(magic_enum::customize::enum_range::min == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::reflected_min>() == 0); REQUIRE(magic_enum::detail::min_v> == 0); REQUIRE(magic_enum::customize::enum_range::min == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::reflected_min>() == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::min_v> == -12); REQUIRE(magic_enum::customize::enum_range::min == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::reflected_min>() == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::min_v> == 1); REQUIRE(magic_enum::customize::enum_range::min == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::reflected_min>() == MAGIC_ENUM_RANGE_MIN); REQUIRE(magic_enum::detail::min_v> == -120); REQUIRE(magic_enum::customize::enum_range::min == 100); REQUIRE(magic_enum::detail::reflected_min>() == 100); REQUIRE(magic_enum::detail::min_v> == 100); REQUIRE(magic_enum::detail::reflected_min>() == 0); REQUIRE(magic_enum::detail::min_v> == false); REQUIRE(magic_enum::detail::reflected_min>() == 0); REQUIRE(magic_enum::detail::min_v> == 0); } SECTION("max") { REQUIRE(magic_enum::customize::enum_range::max == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::reflected_max>() == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::max_v> == 2); REQUIRE(magic_enum::customize::enum_range::max == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::reflected_max>() == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::max_v> == 15); REQUIRE(magic_enum::customize::enum_range::max == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::reflected_max>() == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::max_v> == 3); REQUIRE(magic_enum::customize::enum_range::max == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::reflected_max>() == MAGIC_ENUM_RANGE_MAX); REQUIRE(magic_enum::detail::max_v> == 120); REQUIRE(magic_enum::customize::enum_range::max == 300); REQUIRE(magic_enum::detail::reflected_max>() == 300); REQUIRE(magic_enum::detail::max_v> == 300); REQUIRE(magic_enum::detail::reflected_max>() == 1); REQUIRE(magic_enum::detail::max_v> == true); REQUIRE(magic_enum::detail::reflected_max>() == 64); REQUIRE(magic_enum::detail::max_v> == 63); } } TEST_CASE("cmp_less") { using magic_enum::detail::cmp_less; constexpr std::uint64_t uint64_t_min = std::numeric_limits::min(); constexpr std::uint32_t uint32_t_min = std::numeric_limits::min(); constexpr std::uint32_t uint32_t_max = std::numeric_limits::max(); constexpr std::uint64_t uint64_t_max = std::numeric_limits::max(); constexpr std::int64_t int64_t_min = std::numeric_limits::min(); constexpr std::int32_t int32_t_min = std::numeric_limits::min(); constexpr std::int32_t int32_t_max = std::numeric_limits::max(); constexpr std::int64_t int64_t_max = std::numeric_limits::max(); // Also testing with offset to avoid corner cases. // Two variables to avoid hidden casts: constexpr std::int64_t offset_int64_t = 17; constexpr std::int32_t offset_int32_t = 17; SECTION("same signedness") { REQUIRE(cmp_less(-5, -3)); REQUIRE(cmp_less(27U, 49U)); } SECTION("same signedness, different width") { REQUIRE(cmp_less(uint32_t_max, uint64_t_max)); REQUIRE_FALSE(cmp_less(uint64_t_max, uint32_t_max)); REQUIRE(cmp_less(int64_t_min, int32_t_min)); REQUIRE_FALSE(cmp_less(int32_t_min, int64_t_min)); REQUIRE(cmp_less(int64_t_min + offset_int64_t, int32_t_min + offset_int32_t)); REQUIRE_FALSE(cmp_less(int32_t_min + offset_int32_t, int64_t_min + offset_int64_t)); } SECTION("left signed, right unsigned") { REQUIRE(cmp_less(-5, 3U)); REQUIRE(cmp_less(3, 5U)); } SECTION("left signed, right unsigned, different width") { REQUIRE(cmp_less(int32_t_max, uint64_t_max)); REQUIRE_FALSE(cmp_less(int64_t_max, uint32_t_max)); REQUIRE(cmp_less(int32_t_min, uint64_t_min)); REQUIRE(cmp_less(int64_t_min, uint32_t_min)); REQUIRE(cmp_less(int32_t_max - offset_int32_t, uint64_t_max)); REQUIRE_FALSE(cmp_less(int64_t_max - offset_int64_t, uint32_t_max)); REQUIRE(cmp_less(int32_t_min + offset_int32_t, uint64_t_min)); REQUIRE(cmp_less(int64_t_min + offset_int64_t, uint32_t_min)); } SECTION("left unsigned, right signed") { REQUIRE_FALSE(cmp_less(3U, -5)); REQUIRE(cmp_less(3U, 5)); } SECTION("left unsigned, right signed, different width") { REQUIRE(cmp_less(uint32_t_max, int64_t_max)); REQUIRE_FALSE(cmp_less(uint64_t_max, int32_t_max)); REQUIRE_FALSE(cmp_less(uint32_t_min, int64_t_min)); REQUIRE_FALSE(cmp_less(uint64_t_min, int32_t_min)); REQUIRE(cmp_less(uint32_t_max, int64_t_max - offset_int32_t)); REQUIRE_FALSE(cmp_less(uint64_t_max, int32_t_max - offset_int64_t)); REQUIRE_FALSE(cmp_less(uint32_t_min, int64_t_min + offset_int32_t)); REQUIRE_FALSE(cmp_less(uint64_t_min, int32_t_min + offset_int64_t)); } SECTION("bool, right") { REQUIRE(cmp_less(true, 5)); REQUIRE(cmp_less(false, 1)); REQUIRE_FALSE(cmp_less(false, -1)); } SECTION("left, bool") { REQUIRE_FALSE(cmp_less(5, true)); REQUIRE_FALSE(cmp_less(1, false)); REQUIRE(cmp_less(-1, false)); } } template constexpr std::string_view DoWork() { return "default"; } template <> constexpr std::string_view DoWork() { return "override"; } TEST_CASE("enum_for_each") { SECTION("no return type") { underlying_type_t sum{}; enum_for_each([&sum](auto val) { constexpr underlying_type_t v = enum_integer(val()); sum += v; }); REQUIRE(sum == 10); } SECTION("same return type") { constexpr auto workResults = enum_for_each([](auto val) { return DoWork(); }); REQUIRE(workResults == std::array{"default", "override", "default"}); } SECTION("different return type") { constexpr auto colorInts = enum_for_each([](auto val) { return val; }); REQUIRE(std::is_same_v, std::tuple, enum_constant, enum_constant>>); } } #if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1920 # define MAGIC_ENUM_SUPPORTED_CONSTEXPR_FOR 1 #endif #if defined(MAGIC_ENUM_SUPPORTED_CONSTEXPR_FOR) // from https://artificial-mind.net/blog/2020/10/31/constexpr-for template constexpr void constexpr_for(F&& f) { if constexpr (Start < End) { f(std::integral_constant()); constexpr_for(f); } } template struct Foo {}; TEST_CASE("constexpr_for") { constexpr_for<0, magic_enum::enum_count(), 1>([](auto i) { [[maybe_unused]] Foo()> bar{}; }); constexpr_for<0, magic_enum::enum_count(), 1>([](auto i) { [[maybe_unused]] Foo()> bar{}; }); } #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4064) #endif static int switch_case_2d(Color color, Directions direction) { switch (enum_fuse(color, direction).value()) { case enum_fuse(Color::RED, Directions::Up).value(): return 1; case enum_fuse(Color::BLUE, Directions::Down).value(): return 2; default: return 0; } } enum class Index { zero = 0, one = 1, two = 2 }; static int switch_case_3d(Color color, Directions direction, Index index) { switch (enum_fuse(color, direction, index).value()) { case enum_fuse(Color::RED, Directions::Up, Index::zero).value(): return 1; case enum_fuse(Color::BLUE, Directions::Up, Index::zero).value(): return 2; default: return 0; } } #if defined(_MSC_VER) # pragma warning(pop) #endif TEST_CASE("multdimensional-switch-case") { REQUIRE(switch_case_2d(Color::RED, Directions::Up) == 1); REQUIRE(switch_case_2d(Color::RED, Directions::Down) == 0); REQUIRE(switch_case_2d(Color::BLUE, Directions::Up) == 0); REQUIRE(switch_case_2d(Color::BLUE, Directions::Down) == 2); REQUIRE(switch_case_3d(Color::RED, Directions::Up, Index::zero) == 1); REQUIRE(switch_case_3d(Color::BLUE, Directions::Up, Index::zero) == 2); REQUIRE(switch_case_3d(Color::BLUE, Directions::Up, Index::one) == 0); REQUIRE(switch_case_3d(Color::BLUE, Directions::Up, Index::two) == 0); } #endif #if defined(__cpp_lib_format) #include TEST_CASE("format-base") { REQUIRE(std::format("{}", Color::RED) == "red"); REQUIRE(std::format("{}", Color{0}) == "0"); } #endif TEST_CASE("enum_next_value") { REQUIRE(enum_next_value(Color::RED) == Color::GREEN); REQUIRE(enum_next_value(Color::RED, 2) == Color::BLUE); REQUIRE(enum_next_value(Color::RED, 1) == Color::GREEN); REQUIRE(enum_next_value(Color::RED, 0) == Color::RED); REQUIRE(enum_next_value(Color::BLUE, -2) == Color::RED); REQUIRE(enum_next_value(Color::BLUE, -1) == Color::GREEN); REQUIRE_FALSE(enum_next_value(Color::BLUE).has_value()); REQUIRE_FALSE(enum_next_value(Color::RED, -1).has_value()); REQUIRE_FALSE(enum_next_value(Color::RED, 10).has_value()); } TEST_CASE("enum_next_value_circular") { REQUIRE(enum_next_value_circular(Color::RED) == Color::GREEN); REQUIRE(enum_next_value_circular(Color::RED, 2) == Color::BLUE); REQUIRE(enum_next_value_circular(Color::RED, 1) == Color::GREEN); REQUIRE(enum_next_value_circular(Color::RED, 0) == Color::RED); REQUIRE(enum_next_value_circular(Color::BLUE, -2) == Color::RED); REQUIRE(enum_next_value_circular(Color::BLUE, -1) == Color::GREEN); REQUIRE(enum_next_value_circular(Color::BLUE) == Color::RED); REQUIRE(enum_next_value_circular(Color::BLUE, 4) == Color::RED); REQUIRE(enum_next_value_circular(Color::BLUE, 3) == Color::BLUE); REQUIRE(enum_next_value_circular(Color::BLUE, 2) == Color::GREEN); REQUIRE(enum_next_value_circular(Color::BLUE, 1) == Color::RED); REQUIRE(enum_next_value_circular(Color::BLUE, 0) == Color::BLUE); REQUIRE(enum_next_value_circular(Color::RED, -1) == Color::BLUE); REQUIRE(enum_next_value_circular(Color::RED, -2) == Color::GREEN); REQUIRE(enum_next_value_circular(Color::RED, -3) == Color::RED); REQUIRE(enum_next_value_circular(Color::RED, -4) == Color::BLUE); } TEST_CASE("enum_prev_value") { REQUIRE(enum_prev_value(Color::BLUE) == Color::GREEN); REQUIRE(enum_prev_value(Color::BLUE, 2) == Color::RED); REQUIRE(enum_prev_value(Color::BLUE, 1) == Color::GREEN); REQUIRE(enum_prev_value(Color::RED, -2) == Color::BLUE); REQUIRE(enum_prev_value(Color::RED, -1) == Color::GREEN); REQUIRE(enum_prev_value(Color::BLUE, 0) == Color::BLUE); REQUIRE_FALSE(enum_prev_value(Color::RED).has_value()); REQUIRE_FALSE(enum_prev_value(Color::BLUE, -1).has_value()); REQUIRE_FALSE(enum_prev_value(Color::BLUE, 10).has_value()); } TEST_CASE("enum_prev_value_circular") { REQUIRE(enum_prev_value_circular(Color::RED) == Color::BLUE); REQUIRE(enum_prev_value_circular(Color::RED, 2) == Color::GREEN); REQUIRE(enum_prev_value_circular(Color::RED, 1) == Color::BLUE); REQUIRE(enum_prev_value_circular(Color::RED, 0) == Color::RED); REQUIRE(enum_prev_value_circular(Color::BLUE, -2) == Color::GREEN); REQUIRE(enum_prev_value_circular(Color::BLUE, -1) == Color::RED); REQUIRE(enum_prev_value_circular(Color::BLUE) == Color::GREEN); REQUIRE(enum_prev_value_circular(Color::BLUE, 4) == Color::GREEN); REQUIRE(enum_prev_value_circular(Color::BLUE, 3) == Color::BLUE); REQUIRE(enum_prev_value_circular(Color::BLUE, 2) == Color::RED); REQUIRE(enum_prev_value_circular(Color::BLUE, 1) == Color::GREEN); REQUIRE(enum_prev_value_circular(Color::BLUE, 0) == Color::BLUE); REQUIRE(enum_prev_value_circular(Color::RED, -1) == Color::GREEN); REQUIRE(enum_prev_value_circular(Color::RED, -2) == Color::BLUE); REQUIRE(enum_prev_value_circular(Color::RED, -3) == Color::RED); REQUIRE(enum_prev_value_circular(Color::RED, -4) == Color::GREEN); } TEST_CASE("valid_enum") { //enum Forward1; enum Forward2 : uint32_t; enum class Forward3; enum class Forward4 : uint32_t; enum Empty1 {}; enum Empty2 : uint32_t {}; enum class Empty3 {}; enum class Empty4 : uint32_t {}; //REQUIRE(magic_enum::detail::is_reflected_v>); //REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); REQUIRE(magic_enum::detail::is_reflected_v>); } TEST_CASE("enum_reflected") { REQUIRE(enum_reflected(number::one)); REQUIRE(enum_reflected(number::three)); REQUIRE_FALSE(enum_reflected(number::four)); REQUIRE(enum_reflected(1)); REQUIRE(enum_reflected(234)); REQUIRE_FALSE(enum_reflected(400)); REQUIRE_FALSE(enum_reflected(500)); }