23 #define CATCH_CONFIG_MAIN
26 #define MAGIC_ENUM_NO_CHECK_REFLECTED_ENUM
27 #define MAGIC_ENUM_RANGE_MIN -120
28 #define MAGIC_ENUM_RANGE_MAX 120
36 #include <string_view>
59 #if defined(MAGIC_ENUM_SUPPORTED_ALIASES)
68 static constexpr
int min = 100;
69 static constexpr
int max = 300;
84 INVALID = std::numeric_limits<std::uint8_t>::max()
88 static constexpr
int min = 0;
89 static constexpr
int max = 64;
98 static constexpr
int min = 0;
99 static constexpr
int max = 64;
106 static_assert(
is_magic_enum_supported,
"magic_enum: Unsupported compiler (https://github.com/Neargye/magic_enum#compiler-compatibility).");
110 constexpr
auto cr = enum_cast<Color>(
"red");
113 REQUIRE(enum_cast<Color>(
"blue", [](
char lhs,
char rhs) {
return std::tolower(lhs) == std::tolower(rhs); }).
value() ==
Color::BLUE);
116 constexpr
auto no = enum_cast<Numbers>(
"one");
123 constexpr
auto dr = enum_cast<Directions>(
"Right");
136 constexpr
auto nt = enum_cast<number>(
"three");
143 REQUIRE(enum_cast<crc_hack>(
"b5a7b602ab754d7ab30fb42c4fb28d82").has_value());
144 REQUIRE_FALSE(enum_cast<crc_hack>(
"d19f2e9e82d14b96be4fa12b8a27ee9f").has_value());
146 constexpr
auto crc = enum_cast<crc_hack_2>(
"b5a7b602ab754d7ab30fb42c4fb28d82");
150 REQUIRE(enum_cast<BoolTest>(
"Nay").has_value());
155 constexpr
auto cr = enum_cast<Color>(-12);
161 constexpr
auto no = enum_cast<Numbers>(1);
168 constexpr
auto dr = enum_cast<Directions>(120);
175 constexpr
auto nt = enum_cast<number>(300);
182 REQUIRE(enum_cast<BoolTest>(
false).has_value());
183 REQUIRE(enum_cast<BoolTest>(0).has_value());
192 REQUIRE(enum_integer<Color&>(cg) == 7);
205 REQUIRE(enum_integer<Directions&>(dl) == -120);
226 REQUIRE(enum_index<Color::RED>() == 0);
233 REQUIRE(enum_index<Numbers::one>() == 0);
241 REQUIRE(enum_index<Directions::Left>() == 0);
249 REQUIRE(enum_index<number::one>() == 0);
256 REQUIRE(enum_index<BoolTest::Yay>() == 0);
265 REQUIRE(enum_contains<Color&>(cg));
278 REQUIRE(enum_contains<Directions&>(dl));
295 REQUIRE(enum_contains<Color>(-12));
296 REQUIRE(enum_contains<Color&>(7));
297 REQUIRE(enum_contains<Color>(15));
303 REQUIRE(enum_contains<Numbers>(no));
309 REQUIRE(enum_contains<Directions&>(dr));
316 REQUIRE(enum_contains<number>(100));
317 REQUIRE(enum_contains<number>(200));
318 REQUIRE(enum_contains<number>(300));
325 REQUIRE(enum_contains<BoolTest>(
false));
326 REQUIRE(enum_contains<BoolTest>(0));
330 constexpr
auto cr =
"red";
331 REQUIRE(enum_contains<Color>(cr));
332 REQUIRE(enum_contains<Color&>(
"GREEN"));
333 REQUIRE(enum_contains<Color>(
"blue", [](
char lhs,
char rhs) {
return std::tolower(lhs) == std::tolower(rhs); }));
336 constexpr
auto no = std::string_view{
"one"};
337 REQUIRE(enum_contains<Numbers>(no));
338 REQUIRE(enum_contains<Numbers>(
"two"));
339 REQUIRE(enum_contains<Numbers>(
"three"));
343 auto dr = std::string{
"Right"};
344 REQUIRE(enum_contains<Directions&>(
"Up"));
345 REQUIRE(enum_contains<Directions>(
"Down"));
346 REQUIRE(enum_contains<const Directions>(dr));
347 REQUIRE(enum_contains<Directions>(
"Left"));
350 auto dr2 = std::string{
"RIGHT"};
356 constexpr
auto nt = enum_contains<number>(
"three");
357 REQUIRE(enum_contains<number>(
"one"));
358 REQUIRE(enum_contains<number>(
"two"));
363 REQUIRE(enum_contains<BoolTest>(
"Yay"));
368 constexpr
auto cr = enum_value<Color>(0);
377 constexpr
auto no = enum_value<Numbers>(0);
386 constexpr
auto dr = enum_value<Directions>(3);
397 constexpr
auto nt = enum_value<number>(2);
411 REQUIRE(std::is_same_v<decltype(enum_values<Color>()),
const std::array<Color, 3>&>);
413 constexpr
auto&
s1 = enum_values<Color&>();
416 constexpr
auto&
s2 = enum_values<Numbers>();
419 constexpr
auto&
s3 = enum_values<const Directions>();
422 constexpr
auto&
s4 = enum_values<number>();
425 constexpr
auto& s5 = enum_values<Binary>();
428 constexpr
auto& s6 = enum_values<MaxUsedAsInvalid>();
433 constexpr
auto s1 = enum_count<Color&>();
436 constexpr
auto s2 = enum_count<Numbers>();
439 constexpr
auto s3 = enum_count<const Directions>();
442 constexpr
auto s4 = enum_count<number>();
445 constexpr
auto s5 = enum_count<Binary>();
448 constexpr
auto s6 = enum_count<MaxUsedAsInvalid>();
458 enum class lt5 { s5, loooooooooooooooooooong5 };
462 enum lt6 {
s6, loooooooooooooooooooong6 };
472 enum class lt5 { s5, loooooooooooooooooooong5 };
476 enum lt6 {
s6, loooooooooooooooooooong6 };
488 enum class lt5 { s5, loooooooooooooooooooong5 };
492 enum lt6 {
s6, loooooooooooooooooooong6 };
504 enum class a_lt5 { s5, loooooooooooooooooooong5 };
508 enum a_lt6 { s6, loooooooooooooooooooong6 };
524 REQUIRE(enum_name<Color&>(cb) ==
"BLUE");
540 REQUIRE(enum_name<Directions&>(du) ==
"Up");
609 REQUIRE(
enum_name(a_lt3::loooooooooooooooooooong3) ==
"loooooooooooooooooooong3");
611 REQUIRE(
enum_name(a_lt4::loooooooooooooooooooong4) ==
"loooooooooooooooooooong4");
613 REQUIRE(
enum_name(a_foo1::a_lt5::loooooooooooooooooooong5) ==
"loooooooooooooooooooong5");
615 REQUIRE(
enum_name(a_foo2::loooooooooooooooooooong6) ==
"loooooooooooooooooooong6");
623 constexpr
auto cr_name = enum_name<cr>();
626 REQUIRE(enum_name<Color::BLUE>() ==
"BLUE");
630 constexpr
auto no_name = enum_name<no>();
632 REQUIRE(enum_name<Numbers::two>() ==
"two");
633 REQUIRE(enum_name<Numbers::three>() ==
"three");
634 REQUIRE(enum_name<Numbers::many>() ==
"many");
637 constexpr
auto dr_name = enum_name<dr>();
638 REQUIRE(enum_name<Directions::Up>() ==
"Up");
639 REQUIRE(enum_name<Directions::Down>() ==
"Down");
641 REQUIRE(enum_name<Directions::Left>() ==
"Left");
644 constexpr
auto nt_name = enum_name<nt>();
645 REQUIRE(enum_name<number::one>() ==
"one");
646 REQUIRE(enum_name<number::two>() ==
"two");
648 REQUIRE(enum_name<number::four>() ==
"four");
650 REQUIRE(enum_name<Binary::ONE>() ==
"ONE");
651 REQUIRE(enum_name<MaxUsedAsInvalid::ONE>() ==
"ONE");
654 SECTION(
"empty if the value is out of range") {
656 const auto ln_name =
enum_name(ln_value);
663 REQUIRE(std::is_same_v<decltype(enum_names<Color>()),
const std::array<std::string_view, 3>&>);
665 constexpr
auto&
s1 = enum_names<Color&>();
666 REQUIRE(
s1 == std::array<std::string_view, 3>{{
"red",
"GREEN",
"BLUE"}});
668 constexpr
auto&
s2 = enum_names<Numbers>();
669 REQUIRE(
s2 == std::array<std::string_view, 3>{{
"one",
"two",
"three"}});
671 constexpr
auto&
s3 = enum_names<const Directions>();
672 REQUIRE(
s3 == std::array<std::string_view, 4>{{
"Left",
"Down",
"Up",
"Right"}});
674 constexpr
auto&
s4 = enum_names<number>();
675 REQUIRE(
s4 == std::array<std::string_view, 3>{{
"one",
"two",
"three"}});
679 REQUIRE(std::is_same_v<decltype(enum_entries<Color>()),
const std::array<std::pair<Color, std::string_view>, 3>&>);
681 constexpr
auto&
s1 = enum_entries<Color&>();
684 constexpr
auto&
s2 = enum_entries<Numbers>();
687 constexpr
auto&
s3 = enum_entries<Directions&>();
690 constexpr
auto&
s4 = enum_entries<number>();
695 auto test_ostream = [](
auto e, std::string name) {
697 std::stringstream ss;
703 test_ostream(std::make_optional(
Color::RED),
"red");
706 test_ostream(
static_cast<Color>(0),
"0");
707 test_ostream(std::make_optional(
static_cast<Color>(0)),
"0");
713 test_ostream(
static_cast<Numbers>(0),
"0");
714 test_ostream(std::make_optional(
static_cast<Numbers>(0)),
"0");
720 test_ostream(
static_cast<Directions>(0),
"0");
721 test_ostream(std::make_optional(
static_cast<Directions>(0)),
"0");
723 test_ostream(std::make_optional(
number::one),
"one");
727 test_ostream(
static_cast<number>(0),
"0");
728 test_ostream(std::make_optional(
static_cast<number>(0)),
"0");
732 auto test_istream = [](
const auto e, std::string name) {
734 std::istringstream ss(name);
735 std::decay_t<decltype(e)> v;
844 REQUIRE(is_unscoped_enum_v<Directions>);
845 REQUIRE(is_unscoped_enum_v<number>);
847 REQUIRE(is_scoped_enum_v<Color>);
848 REQUIRE(is_scoped_enum_v<Numbers>);
854 REQUIRE(enum_type_name<Color&>() ==
"Color");
855 REQUIRE(enum_type_name<const Numbers>() ==
"Numbers");
856 REQUIRE(enum_type_name<const Directions&>() ==
"Directions");
857 REQUIRE(enum_type_name<number>() ==
"number");
859 REQUIRE(enum_type_name<lt1>() ==
"lt1");
860 REQUIRE(enum_type_name<lt2>() ==
"lt2");
861 REQUIRE(enum_type_name<lt3>() ==
"lt3");
862 REQUIRE(enum_type_name<lt4>() ==
"lt4");
863 REQUIRE(enum_type_name<foo1::lt5>() ==
"lt5");
864 REQUIRE(enum_type_name<foo2::lt6>() ==
"lt6");
867 REQUIRE(enum_type_name<boo1::lt1>() ==
"lt1");
868 REQUIRE(enum_type_name<boo1::lt2>() ==
"lt2");
869 REQUIRE(enum_type_name<boo1::lt3>() ==
"lt3");
870 REQUIRE(enum_type_name<boo1::lt4>() ==
"lt4");
871 REQUIRE(enum_type_name<boo1::foo1::lt5>() ==
"lt5");
872 REQUIRE(enum_type_name<boo1::foo2::lt6>() ==
"lt6");
875 REQUIRE(enum_type_name<boo2::boo3::lt1>() ==
"lt1");
876 REQUIRE(enum_type_name<boo2::boo3::lt2>() ==
"lt2");
877 REQUIRE(enum_type_name<boo2::boo3::lt3>() ==
"lt3");
878 REQUIRE(enum_type_name<boo2::boo3::lt4>() ==
"lt4");
879 REQUIRE(enum_type_name<boo2::boo3::foo1::lt5>() ==
"lt5");
880 REQUIRE(enum_type_name<boo2::boo3::foo2::lt6>() ==
"lt6");
883 REQUIRE(enum_type_name<a_lt1>() ==
"a_lt1");
884 REQUIRE(enum_type_name<a_lt2>() ==
"a_lt2");
885 REQUIRE(enum_type_name<a_lt3>() ==
"a_lt3");
886 REQUIRE(enum_type_name<a_lt4>() ==
"a_lt4");
887 REQUIRE(enum_type_name<a_foo1::a_lt5>() ==
"a_lt5");
888 REQUIRE(enum_type_name<a_foo2::a_lt6>() ==
"a_lt6");
892 #if defined(MAGIC_ENUM_SUPPORTED_ALIASES)
894 REQUIRE(enum_count<number>() == 3);
914 enum class BadColor : std::uint64_t {
922 NONE = std::numeric_limits<std::uint64_t>::max()
925 REQUIRE(magic_enum::enum_name<BadColor>(BadColor::NONE).empty());
926 REQUIRE_FALSE(enum_cast<BadColor>(std::numeric_limits<std::uint64_t>::max()).has_value());
927 REQUIRE_FALSE(magic_enum::enum_contains<BadColor>(std::numeric_limits<std::uint64_t>::max()));
928 REQUIRE_FALSE(magic_enum::enum_contains<BadColor>(BadColor::NONE));
990 constexpr std::uint64_t uint64_t_min = std::numeric_limits<std::uint64_t>::min();
991 constexpr std::uint32_t uint32_t_min = std::numeric_limits<std::uint32_t>::min();
992 constexpr std::uint32_t uint32_t_max = std::numeric_limits<std::uint32_t>::max();
993 constexpr std::uint64_t uint64_t_max = std::numeric_limits<std::uint64_t>::max();
995 constexpr std::int64_t int64_t_min = std::numeric_limits<std::int64_t>::min();
996 constexpr std::int32_t int32_t_min = std::numeric_limits<std::int32_t>::min();
997 constexpr std::int32_t int32_t_max = std::numeric_limits<std::int32_t>::max();
998 constexpr std::int64_t int64_t_max = std::numeric_limits<std::int64_t>::max();
1002 constexpr std::int64_t offset_int64_t = 17;
1003 constexpr std::int32_t offset_int32_t = 17;
1010 SECTION(
"same signedness, different width") {
1015 REQUIRE(
cmp_less(int64_t_min + offset_int64_t, int32_t_min + offset_int32_t));
1019 SECTION(
"left signed, right unsigned") {
1024 SECTION(
"left signed, right unsigned, different width") {
1035 SECTION(
"left unsigned, right signed") {
1040 SECTION(
"left unsigned, right signed, different width") {
1070 constexpr std::string_view DoWork<Color::GREEN>() {
1077 enum_for_each<Color>([&sum](
auto val) {
1085 constexpr
auto workResults = enum_for_each<Color>([](
auto val) {
1086 return DoWork<val>();
1088 REQUIRE(workResults == std::array<std::string_view, 3>{
"default",
"override",
"default"});
1091 SECTION(
"different return type") {
1092 constexpr
auto colorInts = enum_for_each<Color>([](
auto val) {
1096 REQUIRE(std::is_same_v<std::remove_const_t<decltype(colorInts)>,
1103 #if defined(__clang__) && __clang_major__ >= 5 || defined(__GNUC__) && __GNUC__ >= 9 || defined(_MSC_VER) && _MSC_VER >= 1920
1104 # define MAGIC_ENUM_SUPPORTED_CONSTEXPR_FOR 1
1107 #if defined(MAGIC_ENUM_SUPPORTED_CONSTEXPR_FOR)
1110 template <auto Start, auto End, auto Inc,
class F>
1111 constexpr
void constexpr_for(F&& f) {
1112 if constexpr (Start < End) {
1113 f(std::integral_constant<decltype(Start), Start>());
1114 constexpr_for<Start + Inc, End, Inc>(f);
1118 template <
typename E, E V>
1122 constexpr_for<0, magic_enum::enum_count<Color>(), 1>([](
auto i) {
1123 [[maybe_unused]] Foo<Color, magic_enum::enum_value<Color, i>()> bar{};
1126 constexpr_for<0, magic_enum::enum_count<Numbers>(), 1>([](
auto i) {
1127 [[maybe_unused]] Foo<Numbers, magic_enum::enum_value<Numbers, i>()> bar{};
1131 #if defined(_MSC_VER)
1132 # pragma warning(push)
1133 # pragma warning(disable : 4064)
1147 enum class Index { zero = 0,
one = 1,
two = 2 };
1149 static int switch_case_3d(
Color color,
Directions direction, Index index) {
1160 #if defined(_MSC_VER)
1161 # pragma warning(pop)
1164 TEST_CASE(
"multdimensional-switch-case") {
1177 #if defined(__cpp_lib_format)
1253 enum Forward2 : uint32_t;
1254 enum class Forward3;
1255 enum class Forward4 : uint32_t;
1257 enum Empty2 : uint32_t {};
1258 enum class Empty3 {};
1259 enum class Empty4 : uint32_t {};
1283 REQUIRE(enum_reflected<number>(100));
1284 REQUIRE(enum_reflected<number>(101));
1285 REQUIRE(enum_reflected<number>(234));
1286 REQUIRE(enum_reflected<number>(300));