初始化内容

This commit is contained in:
2026-09-16 14:07:40 +08:00
parent 6934b390bf
commit 4f643c1e7c
18350 changed files with 6088489 additions and 305 deletions
+2
View File
@@ -0,0 +1,2 @@
import %workspace%/../.bazelrc
+23
View File
@@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
_TESTS = [
"test",
"test_flags",
]
_MSVC_FLAGS = ["/std:c++17", "/permissive-"]
_COPTS = select({
"//conditions:default": ["-std=c++17"],
"@rules_cc//cc/compiler:msvc-cl": _MSVC_FLAGS,
"@rules_cc//cc/compiler:clang-cl": _MSVC_FLAGS,
})
[cc_test(
name = test,
srcs = ["{}.cpp".format(test)],
deps = ["@magic_enum", ":catch2"],
copts = _COPTS,
) for test in _TESTS]
# bazel central registry has a catch2 module, but is newer than the one included
# in this repository
cc_library(
name = "catch2",
includes = ["3rdparty/Catch2/include"],
hdrs = ["3rdparty/Catch2/include/catch2/catch.hpp"],
)
+126
View File
@@ -0,0 +1,126 @@
include(CheckCXXCompilerFlag)
if(${MAGIC_ENUM_OPT_TEST_INSTALLED_VERSION})
find_package(magic_enum REQUIRED magic_enum)
endif()
if(${MAGIC_ENUM_OPT_TEST_INSTALLED_VERSION_PKGCONFIG})
find_package(PkgConfig)
pkg_check_modules(magic_enum magic_enum)
if(NOT magic_enum_FOUND)
message(
WARNING
"magic_enum via pkgconfig is not found. \
Next code will try check possible places for some platforms, \
but there's no guarantee. \
If you know where the magic_enum pkgconfig files (.pc) are, \
then specify yourself variable \$\{CMAKE_PREFIX_PATH\} \
with folder like /a/path/to/magic_enum (for POSIX-like pathes), \
where in the folder exists share/pkgconfig/magic_enum.pc ."
)
if(UNIX AND EXISTS "/usr/local/share/pkgconfig/magic_enum.pc")
message(DEBUG "\$\{CMAKE_PREFIX_PATH\} : ${CMAKE_PREFIX_PATH} ")
set(CMAKE_PREFIX_PATH "/usr/local")
message(DEBUG "\$\{CMAKE_PREFIX_PATH\} : ${CMAKE_PREFIX_PATH} ")
pkg_check_modules(magic_enum magic_enum)
endif()
# code place for future workarounds for other platforms...
if(NOT magic_enum_FOUND)
message(FATAL_ERROR "Could not find magic_enum's config. Read a warning above.")
endif()
endif()
message(DEBUG "magic_enum_FOUND : ${magic_enum_FOUND}")
message(DEBUG "magic_enum_LIBRARIES: ${magic_enum_LIBRARIES}")
message(DEBUG "magic_enum_LINK_LIBRARIES: ${magic_enum_LINK_LIBRARIES}")
message(DEBUG "magic_enum_LIBRARY_DIRS: ${magic_enum_LIBRARY_DIRS}")
message(DEBUG "magic_enum_INCLUDE_DIRS: ${magic_enum_INCLUDE_DIRS}")
message(DEBUG "magic_enum_INCLUDE_DIR: ${magic_enum_INCLUDE_DIR}")
message(DEBUG "magic_enum_LDFLAGS: ${magic_enum_LDFLAGS}")
message(DEBUG "magic_enum_LDFLAGS_OTHER: ${magic_enum_LDFLAGS_OTHER}")
message(DEBUG "magic_enum_CFLAGS: ${magic_enum_CFLAGS}")
message(DEBUG "magic_enum_CFLAGS_OTHER: ${magic_enum_CFLAGS_OTHER}")
message(DEBUG "magic_enum_INCLUDEDIR: ${magic_enum_INCLUDEDIR}")
message(DEBUG "magic_enum_LIBDIR: ${magic_enum_LIBDIR}")
message(DEBUG "magic_enum_PREFIX: ${magic_enum_PREFIX}")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(OPTIONS /W4 /WX)
check_cxx_compiler_flag(/permissive HAS_PERMISSIVE_FLAG)
if(HAS_PERMISSIVE_FLAG)
set(OPTIONS ${OPTIONS} /permissive-)
endif()
check_cxx_compiler_flag(/std:c++20 HAS_CPP20_FLAG)
check_cxx_compiler_flag(/std:c++23 HAS_CPP23_FLAG)
check_cxx_compiler_flag(/std:c++latest HAS_CPPLATEST_FLAG)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(OPTIONS -Wall -Wextra -Wshadow -pedantic-errors -Werror)
check_cxx_compiler_flag(-std=c++20 HAS_CPP20_FLAG)
check_cxx_compiler_flag(-std=c++23 HAS_CPP23_FLAG)
endif()
function(make_test src target std)
add_executable(${target} ${src})
target_compile_options(${target} PRIVATE ${OPTIONS})
target_include_directories(${target} PRIVATE 3rdparty/Catch2/include)
if(${MAGIC_ENUM_OPT_TEST_INSTALLED_VERSION_PKGCONFIG})
target_include_directories(${target} PRIVATE ${magic_enum_INCLUDE_DIRS})
else()
target_link_libraries(${target} PRIVATE magic_enum::magic_enum)
endif()
set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF)
if(std)
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
target_compile_options(${target} PRIVATE /std:${std})
else()
target_compile_options(${target} PRIVATE -std=${std})
endif()
endif()
add_test(NAME ${target} COMMAND ${target})
endfunction()
make_test(test.cpp test-cpp17 c++17)
make_test(test_flags.cpp test_flags-cpp17 c++17)
make_test(test_aliases.cpp test_aliases-cpp17 c++17)
make_test(test_containers.cpp test_containers-cpp17 c++17)
make_test(test_wchar_t.cpp test_wchar_t-cpp17 c++17)
if(MAGIC_ENUM_OPT_ENABLE_NONASCII)
make_test(test_nonascii.cpp test_nonascii-cpp17 c++17)
endif()
if(HAS_CPP20_FLAG)
make_test(test.cpp test-cpp20 c++20)
make_test(test_flags.cpp test_flags-cpp20 c++20)
make_test(test_aliases.cpp test_aliases-cpp20 c++20)
make_test(test_containers.cpp test_containers-cpp20 c++20)
make_test(test_wchar_t.cpp test_wchar_t-cpp20 c++20)
if(MAGIC_ENUM_OPT_ENABLE_NONASCII)
make_test(test_nonascii.cpp test_nonascii-cpp20 c++20)
endif()
endif()
if(HAS_CPP23_FLAG)
make_test(test.cpp test-cpp23 c++23)
make_test(test_flags.cpp test_flags-cpp23 c++23)
make_test(test_aliases.cpp test_aliases-cpp23 c++23)
make_test(test_containers.cpp test_containers-cpp23 c++23)
make_test(test_wchar_t.cpp test_wchar_t-cpp23 c++23)
if(MAGIC_ENUM_OPT_ENABLE_NONASCII)
make_test(test_nonascii.cpp test_nonascii-cpp23 c++23)
endif()
endif()
if(HAS_CPPLATEST_FLAG)
make_test(test.cpp test-cpplatest c++latest)
make_test(test_flags.cpp test_flags-cpplatest c++latest)
make_test(test_aliases.cpp test_aliases-cpplatest c++latest)
make_test(test_containers.cpp test_containers-cpplatest c++latest)
make_test(test_wchar_t.cpp test_wchar_t-cpplatest c++latest)
if(MAGIC_ENUM_OPT_ENABLE_NONASCII)
make_test(test_nonascii.cpp test_nonascii-cpplatest c++latest)
endif()
endif()
+6
View File
@@ -0,0 +1,6 @@
module(name = "magic_enum_tests")
bazel_dep(name = "magic_enum")
local_path_override(module_name = "magic_enum", path = "..")
bazel_dep(name = "rules_cc", version = "0.0.8")
View File
+17
View File
@@ -0,0 +1,17 @@
catch2_dep = declare_dependency(include_directories: '3rdparty/Catch2/include')
test_files = {
'basic test': files('test.cpp'),
'flags test': files('test_flags.cpp'),
}
foreach test_name, test_src : test_files
test_exe = executable(
test_name.underscorify(),
test_src,
dependencies: [magic_enum_dep, catch2_dep],
)
test(test_name, test_exe)
endforeach
+1288
View File
File diff suppressed because it is too large Load Diff
+137
View File
@@ -0,0 +1,137 @@
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2024 Daniil Goncharov <neargye@gmail.com>.
//
// 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.
#include <optional>
#include <string>
#include <string_view>
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
template <typename T>
struct MyOpt {
constexpr MyOpt() : mHasValue{false}, val{} {} // required
constexpr MyOpt(const T& v) : mHasValue{true}, val{v} {} // required
constexpr const T& operator*() const { return val; } // required
constexpr explicit operator bool() const { return mHasValue; } // required
constexpr bool has_value() const { return mHasValue; }
constexpr const T& value() const { return val; }
private:
bool mHasValue;
T val;
};
struct MyString {
using value_type = char; // required
static constexpr auto npos = std::string_view::npos; // required
MyString() : str{} {} // required
MyString(const char* s, std::size_t l) : str{s, l} {} // required
bool empty() const { return str.empty(); } // required
auto begin() const { return str.begin(); } // required
auto end() const { return str.end(); } // required
void append(std::size_t count, char c) { str.append(count, c); } // required
void append(const char* s, std::size_t size) { str.append(s, size); } // required
std::size_t size() const { return str.size(); }
int compare(const char* s) const { return str.compare(s); }
private:
std::string str;
};
struct MyStringView {
using value_type = char; // required
static constexpr auto npos = std::string_view::npos; // required
constexpr MyStringView() : str{} {} // required
constexpr MyStringView(const char* cstr, std::size_t size) : str{cstr, size} {} // required
constexpr bool empty() const { return str.empty(); } // required
constexpr std::size_t size() const { return str.size(); } // required
constexpr const char* data() const { return str.data(); } // required
constexpr const char& operator[](std::size_t i) const { return str[i]; } // required
constexpr auto begin() const { return str.begin(); } // required
constexpr auto end() const { return str.end(); } // required
constexpr std::size_t find(char c) const { return str.find(c); } // required
constexpr MyStringView substr(std::size_t p, std::size_t n) { return str.substr(p, n); } // required
constexpr void remove_prefix(std::size_t n) { str.remove_prefix(n); } // required
constexpr void remove_suffix(std::size_t n) { str.remove_suffix(n); } // required
friend constexpr bool operator==(MyStringView lhs, MyStringView rhs); // required
constexpr MyStringView(const char* cstr) : str{ cstr } {}
constexpr int compare(const char* s) const { return str.compare(s); }
private:
std::string_view str;
constexpr MyStringView(std::string_view s) : str{s} {}
};
constexpr bool operator==(MyStringView lhs, MyStringView rhs) {
return lhs.str == rhs.str;
}
#define MAGIC_ENUM_USING_ALIAS_OPTIONAL template<typename T> using optional = MyOpt<T>;
#define MAGIC_ENUM_USING_ALIAS_STRING using string = MyString;
#define MAGIC_ENUM_USING_ALIAS_STRING_VIEW using string_view = MyStringView;
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_flags.hpp>
using namespace magic_enum;
using namespace magic_enum::bitwise_operators;
enum class Color { RED = 1, GREEN = 2, BLUE = 4 };
TEST_CASE("optional") {
constexpr auto cr = enum_cast<Color>("RED");
REQUIRE(cr.has_value());
REQUIRE(cr.value() == Color::RED);
constexpr auto cn = enum_cast<Color>("NONE");
REQUIRE_FALSE(cn.has_value());
}
TEST_CASE("string") {
auto cr = enum_flags_name(Color::RED);
REQUIRE_FALSE(cr.empty());
REQUIRE(cr.compare("RED") == 0);
auto crg = enum_flags_name(Color::RED | Color::GREEN);
REQUIRE_FALSE(crg.empty());
REQUIRE(crg.compare("RED|GREEN") == 0);
auto cn = enum_flags_name(Color{0});
REQUIRE(cn.empty());
REQUIRE(cn.size() == 0);
}
TEST_CASE("string_view") {
auto cr = enum_name(Color::RED);
REQUIRE_FALSE(cr.empty());
REQUIRE(cr.compare("RED") == 0);
auto cn = enum_name(Color{0});
REQUIRE(cn.empty());
REQUIRE(cn.size() == 0);
}
+313
View File
@@ -0,0 +1,313 @@
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2024 Daniil Goncharov <neargye@gmail.com>.
// Copyright (c) 2022 - 2023 Bela Schaum <schaumb@gmail.com>.
//
// 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.
#if defined(__clang__)
# pragma clang diagnostic push
#elif defined(__GNUC__)
# pragma GCC diagnostic push
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4244) // warning C4244: 'argument': conversion from 'const T' to 'unsigned int', possible loss of data.
#endif
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <magic_enum/magic_enum_containers.hpp>
#include <magic_enum/magic_enum_iostream.hpp>
#include <functional>
enum class Color { RED = 1, GREEN = 2, BLUE = 4 };
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};
enum class Empty {};
struct RGB {
std::uint8_t r {};
std::uint8_t g {};
std::uint8_t b {};
[[nodiscard]] constexpr bool empty() { return std::equal_to{}(r, g) && std::equal_to{}(g, b) && std::equal_to{}(b, 0); }
[[nodiscard]] constexpr bool operator==(RGB rgb) const noexcept { return std::equal_to{}(r, rgb.r) && std::equal_to{}(g, rgb.g) && std::equal_to{}(b, rgb.b); }
friend std::ostream& operator<<(std::ostream& ostream, RGB rgb) {
ostream << "R=" << static_cast<std::uint32_t>(rgb.r) << " G=" << static_cast<std::uint32_t>(rgb.g) << " B=" << static_cast<std::uint32_t>(rgb.b);
return ostream;
}
};
template <typename T> bool check_const([[maybe_unused]]T& element) { return false; }
template <typename T> bool check_const([[maybe_unused]]T const& element) { return true; }
constexpr std::uint8_t color_max = std::numeric_limits<std::uint8_t>::max();
TEST_CASE("containers_array") {
using namespace magic_enum::bitwise_operators;
using namespace magic_enum::ostream_operators;
constexpr magic_enum::containers::array<Color, RGB> color_rgb_initializer {{{{color_max, 0, 0}, {0, color_max, 0}, {0, 0, color_max}}}};
REQUIRE(color_rgb_initializer.at(Color::RED) == RGB{color_max, 0, 0});
REQUIRE(color_rgb_initializer.at(Color::GREEN) == RGB{0, color_max, 0});
REQUIRE(color_rgb_initializer.at(Color::BLUE) == RGB{0, 0, color_max});
/* BUG: a sort will not survive the data integration */
magic_enum::containers::array<Color, std::uint8_t> color_rgb_container_int{{1U, 4U, 2U}};
// ENC: Direct convert to std::array
// std::array compare_before {1U, 4U, 2U};
constexpr magic_enum::containers::array<Color, std::uint8_t> compare_before{{1U, 4U, 2U}};
REQUIRE(color_rgb_container_int == compare_before);
constexpr auto colors = magic_enum::enum_values<Color>();
std::ignore = magic_enum::containers::get<0>(compare_before);
std::ignore = magic_enum::containers::get<1>(compare_before);
std::ignore = magic_enum::containers::get<2>(compare_before);
std::ignore = magic_enum::containers::get<Color::RED>(compare_before);
std::ignore = magic_enum::containers::get<Color::GREEN>(compare_before);
std::ignore = magic_enum::containers::get<Color::BLUE>(compare_before);
REQUIRE(std::make_pair(colors[0], color_rgb_container_int[colors[0]]) == std::make_pair<Color, std::uint8_t>(Color::RED, 1U));
REQUIRE(std::make_pair(colors[1], color_rgb_container_int[colors[1]]) == std::make_pair<Color, std::uint8_t>(Color::GREEN, 4U));
REQUIRE(std::make_pair(colors[2], color_rgb_container_int[colors[2]]) == std::make_pair<Color, std::uint8_t>(Color::BLUE, 2U));
std::sort(std::begin(color_rgb_container_int), std::end(color_rgb_container_int));
// Missing: Direct convert to std::array
// std::array compare_after {1U, 2U, 4U};
constexpr magic_enum::containers::array<Color, std::uint8_t> compare_after{{1U, 2U, 4U}};
REQUIRE(color_rgb_container_int == compare_after);
std::ignore = magic_enum::containers::get<0>(compare_after);
std::ignore = magic_enum::containers::get<1>(compare_after);
std::ignore = magic_enum::containers::get<2>(compare_after);
std::ignore = magic_enum::containers::get<Color::RED>(compare_after);
std::ignore = magic_enum::containers::get<Color::GREEN>(compare_after);
std::ignore = magic_enum::containers::get<Color::BLUE>(compare_after);
REQUIRE(std::make_pair(colors[0], color_rgb_container_int[colors[0]]) == std::make_pair<Color, std::uint8_t>(Color::RED, 1U));
REQUIRE(std::make_pair(colors[1], color_rgb_container_int[colors[1]]) == std::make_pair<Color, std::uint8_t>(Color::GREEN, 2U));
REQUIRE(std::make_pair(colors[2], color_rgb_container_int[colors[2]]) == std::make_pair<Color, std::uint8_t>(Color::BLUE, 4U));
auto color_rgb_container = magic_enum::containers::array<Color, RGB>();
REQUIRE_FALSE(color_rgb_container.empty());
REQUIRE(color_rgb_container.size() == 3);
REQUIRE(magic_enum::enum_count<Color>() == color_rgb_container.size());
REQUIRE(color_rgb_container.at(Color::RED).empty());
REQUIRE(color_rgb_container.at(Color::GREEN).empty());
REQUIRE(color_rgb_container.at(Color::BLUE).empty());
REQUIRE_THROWS(color_rgb_container.at(Color::BLUE|Color::GREEN).empty());
color_rgb_container[Color::RED] = {color_max, 0, 0};
color_rgb_container[Color::GREEN] = {0, color_max, 0};
color_rgb_container[Color::BLUE] = {0, 0, color_max};
REQUIRE(color_rgb_container.at(Color::RED) == RGB{color_max, 0, 0});
REQUIRE(color_rgb_container.at(Color::GREEN) == RGB{0, color_max, 0});
REQUIRE(color_rgb_container.at(Color::BLUE) == RGB{0, 0, color_max});
REQUIRE(color_rgb_container.front() == RGB{color_max, 0, 0});
REQUIRE(color_rgb_container.back() == RGB{0, 0, color_max});
REQUIRE(magic_enum::containers::get<Color::RED>(color_rgb_container) == RGB{color_max, 0, 0});
REQUIRE(magic_enum::containers::get<Color::GREEN>(color_rgb_container) == RGB{0, color_max, 0});
REQUIRE(magic_enum::containers::get<Color::BLUE>(color_rgb_container) == RGB{0, 0, color_max});
auto iterator = color_rgb_container.begin();
REQUIRE_FALSE(check_const(iterator));
REQUIRE(check_const(color_rgb_container.begin()));
REQUIRE(check_const(color_rgb_container.cbegin()));
auto color_rgb_container_compare = magic_enum::containers::array<Color, RGB>();
color_rgb_container_compare.fill({color_max, color_max, color_max});
REQUIRE_FALSE(color_rgb_container == color_rgb_container_compare);
color_rgb_container_compare[Color::RED] = {color_max, 0, 0};
color_rgb_container_compare[Color::GREEN] = {0, color_max, 0};
color_rgb_container_compare[Color::BLUE] = {0, 0, color_max};
REQUIRE(color_rgb_container == color_rgb_container_compare);
constexpr auto from_to_array = magic_enum::containers::to_array<Color, RGB>({{color_max, 0, 0}, {0, color_max, 0}, {0, 0, color_max}});
REQUIRE(from_to_array.at(Color::RED) == RGB{color_max, 0, 0});
REQUIRE(from_to_array.at(Color::GREEN) == RGB{0, color_max, 0});
REQUIRE(from_to_array.at(Color::BLUE) == RGB{0, 0, color_max});
}
TEST_CASE("containers_bitset") {
using namespace magic_enum::bitwise_operators;
auto color_bitset = magic_enum::containers::bitset<Color>();
REQUIRE(color_bitset.to_string().empty());
REQUIRE(color_bitset.size() == 3);
REQUIRE(magic_enum::enum_count<Color>() == color_bitset.size());
REQUIRE_FALSE(color_bitset.all());
REQUIRE_FALSE(color_bitset.any());
REQUIRE(color_bitset.none());
REQUIRE(color_bitset.count() == 0);
color_bitset.set(Color::GREEN);
REQUIRE_FALSE(color_bitset.all());
REQUIRE(color_bitset.any());
REQUIRE_FALSE(color_bitset.none());
REQUIRE(color_bitset.count() == 1);
REQUIRE_FALSE(color_bitset.test(Color::RED));
REQUIRE(color_bitset.test(Color::GREEN));
REQUIRE_FALSE(color_bitset.test(Color::BLUE));
color_bitset.set(Color::BLUE);
REQUIRE_FALSE(color_bitset.all());
REQUIRE(color_bitset.any());
REQUIRE_FALSE(color_bitset.none());
REQUIRE(color_bitset.count() == 2);
REQUIRE_FALSE(color_bitset.test(Color::RED));
REQUIRE(color_bitset.test(Color::GREEN));
REQUIRE(color_bitset.test(Color::BLUE));
color_bitset.set(Color::RED);
REQUIRE(color_bitset.all());
REQUIRE(color_bitset.any());
REQUIRE_FALSE(color_bitset.none());
REQUIRE(color_bitset.count() == 3);
REQUIRE(color_bitset.test(Color::RED));
REQUIRE(color_bitset.test(Color::GREEN));
REQUIRE(color_bitset.test(Color::BLUE));
color_bitset.reset();
REQUIRE_FALSE(color_bitset.all());
REQUIRE_FALSE(color_bitset.any());
REQUIRE(color_bitset.none());
REQUIRE(color_bitset.count() == 0);
REQUIRE_FALSE(color_bitset.test(Color::RED));
REQUIRE_FALSE(color_bitset.test(Color::GREEN));
REQUIRE_FALSE(color_bitset.test(Color::BLUE));
color_bitset.set(Color::RED);
REQUIRE(color_bitset.test(Color::RED));
REQUIRE_FALSE(color_bitset.test(Color::GREEN));
REQUIRE_FALSE(color_bitset.test(Color::BLUE));
color_bitset.flip();
REQUIRE_FALSE(color_bitset.test(Color::RED));
REQUIRE(color_bitset.test(Color::GREEN));
REQUIRE(color_bitset.test(Color::BLUE));
constexpr magic_enum::containers::bitset<Color> color_bitset_all {Color::RED|Color::GREEN|Color::BLUE};
REQUIRE(color_bitset_all.to_string() == "RED|GREEN|BLUE");
REQUIRE(color_bitset_all.to_string( {}, '0', '1' ) == "111");
REQUIRE(color_bitset_all.to_ulong( {} ) == 7);
REQUIRE(color_bitset_all.to_ullong( {} ) == 7);
REQUIRE(color_bitset_all.all());
REQUIRE(color_bitset_all.any());
REQUIRE_FALSE(color_bitset_all.none());
constexpr magic_enum::containers::bitset<Color> color_bitset_red_green {Color::RED|Color::GREEN};
REQUIRE(color_bitset_red_green.to_string() == "RED|GREEN");
REQUIRE(color_bitset_red_green.to_string( {}, '0', '1' ) == "110");
REQUIRE(color_bitset_red_green.to_ulong( {} ) == 3);
REQUIRE(color_bitset_red_green.to_ullong( {} ) == 3);
REQUIRE_FALSE(color_bitset_red_green.all());
REQUIRE(color_bitset_red_green.any());
REQUIRE_FALSE(color_bitset_red_green.none());
}
TEST_CASE("containers_set") {
using namespace magic_enum::bitwise_operators;
using namespace magic_enum::ostream_operators;
auto color_set = magic_enum::containers::set<Color>();
REQUIRE(color_set.empty());
REQUIRE(color_set.size() == 0);
REQUIRE_FALSE(magic_enum::enum_count<Color>() == color_set.size());
color_set.insert(Color::RED);
std::ignore = color_set.insert(Color::RED);
color_set.insert(Color::GREEN);
color_set.insert(Color::BLUE);
color_set.insert(Color::RED);
color_set.insert(Color::RED|Color::GREEN);
color_set.insert(Color::RED|Color::BLUE);
color_set.insert(Color::GREEN|Color::BLUE);
color_set.insert(Color::RED|Color::GREEN|Color::BLUE);
REQUIRE_FALSE(color_set.empty());
REQUIRE(color_set.size() == 3);
REQUIRE(magic_enum::enum_count<Color>() == color_set.size());
color_set.erase(Color::RED);
color_set.erase(Color::GREEN);
REQUIRE(magic_enum::enum_count<Color>() - 2 == color_set.size());
REQUIRE(color_set.count(Color::RED) == 0);
REQUIRE_FALSE(color_set.contains(Color::GREEN));
REQUIRE(color_set.contains(Color::BLUE));
auto color_set_compare = magic_enum::containers::set<Color>();
color_set_compare.insert(Color::BLUE);
color_set_compare.insert(Color::RED);
color_set_compare.insert(Color::GREEN);
constexpr magic_enum::containers::set color_set_filled = {Color::RED, Color::GREEN, Color::BLUE};
REQUIRE_FALSE(color_set_filled.empty());
REQUIRE(color_set_filled.size() == 3);
REQUIRE(magic_enum::enum_count<Color>() == color_set_filled.size());
magic_enum::containers::set color_set_not_const = {Color::RED, Color::GREEN, Color::BLUE};
REQUIRE_FALSE(color_set_not_const.empty());
REQUIRE(color_set_not_const.size() == 3);
REQUIRE(magic_enum::enum_count<Color>() == color_set_not_const.size());
color_set_not_const.clear();
REQUIRE(color_set_not_const.empty());
REQUIRE(color_set_not_const.size() == 0);
REQUIRE_FALSE(magic_enum::enum_count<Color>() == color_set_not_const.size());
}
TEST_CASE("map_like_container") {
using namespace magic_enum::ostream_operators;
std::vector<std::pair<Color, RGB>> map {{Color::GREEN, {0, color_max, 0}}, {Color::BLUE, {0, 0, color_max}}, {Color::RED, {color_max, 0, 0}}};
for (auto [key, value] : map) {
std::cout << "Key=" << key << " Value=" << value << std::endl;
}
auto compare = [](std::pair<Color, RGB>& lhs,
std::pair<Color, RGB>& rhs) {
return static_cast<std::int32_t>(lhs.first) < static_cast<std::int32_t>(rhs.first);
};
std::sort(std::begin(map), std::end(map), compare);
for (auto [key, value] : map) {
std::cout << "Key=" << key << " Value=" << value << std::endl;
}
}
+834
View File
@@ -0,0 +1,834 @@
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2024 Daniil Goncharov <neargye@gmail.com>.
//
// 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.
#if defined(__clang__)
# pragma clang diagnostic push
#elif defined(__GNUC__)
# pragma GCC diagnostic push
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4244) // warning C4244: 'argument': conversion from 'const T' to 'unsigned int', possible loss of data.
#endif
#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_flags.hpp>
#include <magic_enum/magic_enum_fuse.hpp>
#include <magic_enum/magic_enum_iostream.hpp>
#include <magic_enum/magic_enum_utility.hpp>
#include <array>
#include <cctype>
#include <string_view>
#include <sstream>
enum class Color { RED = 1, GREEN = 2, BLUE = 4 };
template <>
struct magic_enum::customize::enum_range<Color> {
static constexpr bool is_flags = true;
};
enum class Numbers : int {
none = 0,
one = 1 << 1,
two = 1 << 2,
three = 1 << 3,
many = 1 << 30,
};
template <>
struct magic_enum::customize::enum_range<Numbers> {
static constexpr bool is_flags = true;
};
enum Directions : std::uint64_t {
NoDirection = 0,
Left = std::uint64_t{1} << 10,
Down = std::uint64_t{1} << 20,
Up = std::uint64_t{1} << 31,
Right = std::uint64_t{1} << 63,
};
template <>
struct magic_enum::customize::enum_range<Directions> {
static constexpr bool is_flags = true;
};
enum number : unsigned long {
no_number = 0,
one = 1 << 1,
two = 1 << 2,
three = 1 << 3,
four = 1 << 4,
#if defined(MAGIC_ENUM_SUPPORTED_ALIASES)
_1 = one,
_2 = two,
_3 = three,
_4 = four
#endif
};
template <>
struct magic_enum::customize::enum_range<number> {
static constexpr bool is_flags = true;
};
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_fuse.hpp>
using namespace magic_enum;
using namespace magic_enum::bitwise_operators;
TEST_CASE("enum_cast") {
SECTION("string") {
constexpr auto cr = enum_cast<Color>("RED");
REQUIRE(cr.value() == Color::RED);
REQUIRE(enum_cast<Color&>("GREEN").value() == Color::GREEN);
REQUIRE(enum_cast<Color>("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }).value() == Color::BLUE);
REQUIRE_FALSE(enum_cast<Color&>("blue|RED", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }).has_value());
REQUIRE_FALSE(enum_cast<Color&>("GREEN|RED").has_value());
REQUIRE_FALSE(enum_cast<Color&>("GREEN|RED|RED").has_value());
REQUIRE_FALSE(enum_cast<Color&>("GREEN|RED|None").has_value());
REQUIRE_FALSE(enum_cast<Color>("None").has_value());
REQUIRE(enum_flags_cast<Color&>("GREEN").value() == Color::GREEN);
REQUIRE(enum_flags_cast<Color>("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }).value() == Color::BLUE);
REQUIRE(enum_flags_cast<Color&>("blue|RED", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }).value() == (Color::BLUE | Color::RED));
REQUIRE(enum_flags_cast<Color&>("GREEN|RED").value() == (Color::GREEN | Color::RED));
REQUIRE(enum_flags_cast<Color&>("GREEN|RED|RED").value() == (Color::GREEN | Color::RED));
REQUIRE_FALSE(enum_flags_cast<Color&>("GREEN|RED|None").has_value());
REQUIRE_FALSE(enum_flags_cast<Color>("None").has_value());
constexpr auto no = enum_cast<Numbers>("one");
REQUIRE(no.value() == Numbers::one);
REQUIRE(enum_cast<Numbers>("two").value() == Numbers::two);
REQUIRE(enum_cast<Numbers>("three").value() == Numbers::three);
REQUIRE(enum_cast<Numbers>("many") == Numbers::many);
REQUIRE_FALSE(enum_cast<Numbers>("None").has_value());
constexpr auto dr = enum_cast<Directions>("Right");
REQUIRE(enum_cast<Directions&>("Up").value() == Directions::Up);
REQUIRE(enum_cast<const Directions>("Down").value() == Directions::Down);
REQUIRE(dr.value() == Directions::Right);
REQUIRE(enum_cast<Directions>("Left").value() == Directions::Left);
REQUIRE_FALSE(enum_cast<Directions>("None").has_value());
constexpr auto nto = enum_flags_cast<number>("three|one");
REQUIRE(enum_cast<number>("one").value() == number::one);
REQUIRE(enum_cast<number>("two").value() == number::two);
REQUIRE(enum_cast<number>("three").value() == number::three);
REQUIRE(enum_cast<number>("four") == number::four);
REQUIRE(nto.value() == (number::three | number::one));
REQUIRE_FALSE(enum_cast<number>("None").has_value());
}
SECTION("integer") {
Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE};
constexpr auto cr = enum_cast<Color>(1);
REQUIRE(cr.value() == Color::RED);
REQUIRE(enum_cast<Color&>(2).value() == Color::GREEN);
REQUIRE(enum_cast<Color>(static_cast<int>(cm[2])).value() == Color::BLUE);
REQUIRE_FALSE(enum_cast<Color>(1 | 2).has_value());
REQUIRE_FALSE(enum_cast<Color>(1 | 2 | 1).has_value());
REQUIRE_FALSE(enum_cast<Color>(1 | 2 | 8).has_value());
REQUIRE_FALSE(enum_cast<Color>(0).has_value());
REQUIRE(enum_flags_cast<Color&>(2).value() == Color::GREEN);
REQUIRE(enum_flags_cast<Color>(static_cast<int>(cm[2])).value() == Color::BLUE);
REQUIRE(enum_flags_cast<Color>(1 | 2).value() == (Color::GREEN | Color::RED));
REQUIRE(enum_flags_cast<Color>(1 | 2 | 1).value() == (Color::GREEN | Color::RED));
REQUIRE_FALSE(enum_flags_cast<Color>(1 | 2 | 8).has_value());
REQUIRE_FALSE(enum_flags_cast<Color>(0).has_value());
constexpr auto no = enum_cast<Numbers>(2);
REQUIRE(no.value() == Numbers::one);
REQUIRE(enum_cast<Numbers>(4).value() == Numbers::two);
REQUIRE(enum_cast<Numbers>(8).value() == Numbers::three);
REQUIRE(enum_cast<Numbers>(1 << 30).value() == Numbers::many);
REQUIRE_FALSE(enum_cast<Numbers>(127).has_value());
REQUIRE_FALSE(enum_cast<Numbers>(0).has_value());
constexpr auto dr = enum_cast<Directions>(std::uint64_t{1} << 63);
REQUIRE(enum_cast<Directions&>(std::uint64_t{1} << 31).value() == Directions::Up);
REQUIRE(enum_cast<const Directions>(std::uint64_t{1} << 20).value() == Directions::Down);
REQUIRE(dr.value() == Directions::Right);
REQUIRE(enum_cast<Directions>(std::uint64_t{1} << 10).value() == Directions::Left);
REQUIRE_FALSE(enum_cast<Directions>(0).has_value());
constexpr auto nto = enum_flags_cast<number>(2 | 8);
REQUIRE(enum_cast<number>(1 << 1).value() == number::one);
REQUIRE(enum_cast<number>(1 << 2).value() == number::two);
REQUIRE(enum_cast<number>(1 << 3).value() == number::three);
REQUIRE(enum_cast<number>(1 << 4).value() == number::four);
REQUIRE(nto.value() == (number::three | number::one));
REQUIRE_FALSE(enum_cast<number>(0).has_value());
}
}
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<Color&>(cg).value() == 1);
REQUIRE(enum_index(cm[2]).value() == 2);
REQUIRE_FALSE(enum_index<Color>(Color::RED | Color::GREEN).has_value());
REQUIRE_FALSE(enum_index<Color>(Color::RED | Color::GREEN | Color::RED).has_value());
REQUIRE_FALSE(enum_index<Color>(Color::RED | Color{8}).has_value());
REQUIRE_FALSE(enum_index(static_cast<Color>(0)).has_value());
constexpr auto no = enum_index(Numbers::one);
REQUIRE(no.value() == 0);
REQUIRE(enum_index(Numbers::two).value() == 1);
REQUIRE(enum_index(Numbers::three).value() == 2);
REQUIRE(enum_index(Numbers::many).value() == 3);
REQUIRE_FALSE(enum_index(static_cast<Numbers>(0)).has_value());
constexpr auto dr = enum_index(Directions::Right);
Directions dl = Directions::Left;
REQUIRE(enum_index<Directions&>(dl).value() == 0);
REQUIRE(enum_index<const Directions>(Directions::Down).value() == 1);
REQUIRE(enum_index(Directions::Up).value() == 2);
REQUIRE(dr.value() == 3);
REQUIRE_FALSE(enum_index(static_cast<Directions>(0)).has_value());
constexpr auto nto = enum_index(number::three | number::one);
REQUIRE(enum_index(number::one).value() == 0);
REQUIRE(enum_index(number::two).value() == 1);
REQUIRE(enum_index(number::three).value() == 2);
REQUIRE(enum_index(number::four).value() == 3);
REQUIRE_FALSE(nto.has_value());
REQUIRE_FALSE(enum_index(static_cast<number>(0)).has_value());
}
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<Color&>(cg));
REQUIRE(enum_contains(cm[2]));
REQUIRE_FALSE(enum_contains(static_cast<Color>(0)));
REQUIRE(enum_flags_contains<Color&>(cg));
REQUIRE(enum_flags_contains(cm[2]));
REQUIRE(enum_flags_contains<Color>(Color::RED | Color::GREEN));
REQUIRE(enum_flags_contains<Color>(Color::RED | Color::GREEN | Color::GREEN));
REQUIRE_FALSE(enum_flags_contains<Color>(Color::RED | Color{8}));
REQUIRE_FALSE(enum_flags_contains(static_cast<Color>(0)));
constexpr auto no = enum_contains(Numbers::one);
REQUIRE(no);
REQUIRE(enum_contains(Numbers::two));
REQUIRE(enum_contains(Numbers::three));
REQUIRE(enum_contains(Numbers::many));
REQUIRE_FALSE(enum_contains(static_cast<Numbers>(0)));
constexpr auto dr = enum_contains(Directions::Right);
Directions dl = Directions::Left;
REQUIRE(enum_contains<Directions&>(dl));
REQUIRE(enum_contains<const Directions>(Directions::Down));
REQUIRE(enum_contains(Directions::Up));
REQUIRE(dr);
REQUIRE_FALSE(enum_contains(static_cast<Directions>(0)));
constexpr auto nto = enum_contains(number::three | number::one);
REQUIRE(enum_contains(number::one));
REQUIRE(enum_contains<number&>(number::two));
REQUIRE(enum_contains(number::one));
REQUIRE(enum_contains(number::four));
REQUIRE_FALSE(nto);
REQUIRE_FALSE(enum_contains(static_cast<number>(0)));
REQUIRE(enum_flags_contains(number::three | number::one));
}
SECTION("integer") {
REQUIRE(enum_contains<Color>(1));
REQUIRE(enum_contains<Color&>(2));
REQUIRE(enum_contains<const Color>(4));
REQUIRE_FALSE(enum_contains<Color>(0));
REQUIRE(enum_flags_contains<Color>(1));
REQUIRE(enum_flags_contains<Color&>(2));
REQUIRE(enum_flags_contains<Color>(4));
REQUIRE(enum_flags_contains<Color>(1 | 2));
REQUIRE(enum_flags_contains<Color>(1 | 2 | 1));
REQUIRE_FALSE(enum_flags_contains<Color>(1 | 2 | 8));
REQUIRE_FALSE(enum_flags_contains<Color>(0));
constexpr auto no = enum_contains<Numbers>(1 << 1);
REQUIRE(no);
REQUIRE(enum_contains<Numbers>(1 << 2));
REQUIRE(enum_contains<Numbers>(1 << 3));
REQUIRE(enum_contains<Numbers>(1 << 30));
constexpr auto dr = enum_contains<Directions&>(std::uint64_t{1} << 63);
REQUIRE(dr);
REQUIRE(enum_contains<const Directions>(std::uint64_t{1} << 10));
REQUIRE(enum_contains<Directions>(std::uint64_t{1} << 20));
REQUIRE(enum_contains<Directions>(std::uint64_t{1} << 31));
REQUIRE_FALSE(enum_contains<Directions>(static_cast<Directions>(0)));
constexpr auto nto = enum_contains<number>(8 | 2);
REQUIRE(enum_contains<number>(1 << 1));
REQUIRE(enum_contains<number>(1 << 2));
REQUIRE(enum_contains<number>(1 << 3));
REQUIRE(enum_contains<number>(1 << 4));
REQUIRE_FALSE(enum_contains<number>(8 | 2 | 16));
REQUIRE_FALSE(enum_contains<number>(8 | 16 | 16));
REQUIRE_FALSE(nto);
REQUIRE_FALSE(enum_contains<number>(8 | 64));
REQUIRE_FALSE(enum_contains<number>(0));
}
SECTION("string") {
constexpr auto cr = "RED";
REQUIRE(enum_contains<Color>(cr));
REQUIRE(enum_contains<Color&>("GREEN"));
REQUIRE(enum_contains<const Color>("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }));
REQUIRE_FALSE(enum_contains<Color&>("blue|RED", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }));
REQUIRE_FALSE(enum_contains<Color&>("GREEN|RED"));
REQUIRE_FALSE(enum_contains<Color&>("GREEN|RED|RED"));
REQUIRE_FALSE(enum_contains<Color>("GREEN|RED|None"));
REQUIRE_FALSE(enum_contains<Color>("None"));
REQUIRE(enum_flags_contains<Color&>("GREEN"));
REQUIRE(enum_flags_contains<Color>("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }));
REQUIRE(enum_flags_contains<Color>("blue|RED", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }));
REQUIRE(enum_flags_contains<Color>("GREEN|RED"));
REQUIRE(enum_flags_contains<Color>("GREEN|RED|RED"));
REQUIRE_FALSE(enum_flags_contains<Color>("GREEN|RED|None"));
REQUIRE_FALSE(enum_flags_contains<Color>("None"));
constexpr auto no = std::string_view{"one"};
REQUIRE(enum_contains<Numbers>(no));
REQUIRE(enum_contains<Numbers>("two"));
REQUIRE(enum_contains<Numbers>("three"));
REQUIRE(enum_contains<Numbers>("many"));
REQUIRE_FALSE(enum_contains<Numbers>("None"));
auto dr = std::string{"Right"};
REQUIRE(enum_contains<Directions&>("Up"));
REQUIRE(enum_contains<Directions>("Down"));
REQUIRE(enum_contains<const Directions>(dr));
REQUIRE(enum_contains<Directions>("Left"));
REQUIRE_FALSE(enum_contains<Directions>("None"));
constexpr auto nto = enum_contains<number>("three|one");
REQUIRE(enum_contains<number>("one"));
REQUIRE(enum_contains<number>("two"));
REQUIRE(enum_contains<number>("three"));
REQUIRE(enum_contains<number>("four"));
REQUIRE_FALSE(nto);
REQUIRE_FALSE(enum_contains<number>("None"));
REQUIRE(enum_flags_contains<number>("three|one"));
}
}
TEST_CASE("enum_value") {
constexpr auto cr = enum_value<Color>(0);
REQUIRE(cr == Color::RED);
REQUIRE(enum_value<Color&>(1) == Color::GREEN);
REQUIRE(enum_value<Color>(2) == Color::BLUE);
REQUIRE(enum_value<Color, 0>() == Color::RED);
REQUIRE(enum_value<Color, 1>() == Color::GREEN);
REQUIRE(enum_value<Color, 2>() == Color::BLUE);
constexpr auto no = enum_value<Numbers>(0);
REQUIRE(no == Numbers::one);
REQUIRE(enum_value<Numbers>(1) == Numbers::two);
REQUIRE(enum_value<Numbers>(2) == Numbers::three);
REQUIRE(enum_value<Numbers>(3) == Numbers::many);
REQUIRE(enum_value<Numbers, 0>() == Numbers::one);
REQUIRE(enum_value<Numbers, 1>() == Numbers::two);
REQUIRE(enum_value<Numbers, 2>() == Numbers::three);
REQUIRE(enum_value<Numbers, 3>() == Numbers::many);
constexpr auto dr = enum_value<Directions>(3);
REQUIRE(enum_value<Directions&>(0) == Directions::Left);
REQUIRE(enum_value<const Directions>(1) == Directions::Down);
REQUIRE(enum_value<Directions>(2) == Directions::Up);
REQUIRE(dr == Directions::Right);
REQUIRE(enum_value<Directions, 0>() == Directions::Left);
REQUIRE(enum_value<Directions, 1>() == Directions::Down);
REQUIRE(enum_value<Directions, 2>() == Directions::Up);
REQUIRE(enum_value<Directions, 3>() == Directions::Right);
constexpr auto nt = enum_value<number>(2);
REQUIRE(enum_value<number>(0) == number::one);
REQUIRE(enum_value<number>(1) == number::two);
REQUIRE(nt == number::three);
REQUIRE(enum_value<number>(3) == number::four);
REQUIRE(enum_value<number, 0>() == number::one);
REQUIRE(enum_value<number, 1>() == number::two);
REQUIRE(enum_value<number, 2>() == number::three);
REQUIRE(enum_value<number, 3>() == number::four);
}
TEST_CASE("enum_values") {
REQUIRE(std::is_same_v<decltype(enum_values<Color>()), const std::array<Color, 3>&>);
constexpr auto& s1 = enum_values<Color&>();
REQUIRE(s1 == std::array<Color, 3>{{Color::RED, Color::GREEN, Color::BLUE}});
constexpr auto& s2 = enum_values<Numbers>();
REQUIRE(s2 == std::array<Numbers, 4>{{Numbers::one, Numbers::two, Numbers::three, Numbers::many}});
constexpr auto& s3 = enum_values<const Directions>();
REQUIRE(s3 == std::array<Directions, 4>{{Directions::Left, Directions::Down, Directions::Up, Directions::Right}});
constexpr auto& s4 = enum_values<number>();
REQUIRE(s4 == std::array<number, 4>{{number::one, number::two, number::three, number::four}});
}
TEST_CASE("enum_count") {
constexpr auto s1 = enum_count<Color&>();
REQUIRE(s1 == 3);
constexpr auto s2 = enum_count<Numbers>();
REQUIRE(s2 == 4);
constexpr auto s3 = enum_count<const Directions>();
REQUIRE(s3 == 4);
constexpr auto s4 = enum_count<number>();
REQUIRE(s4 == 4);
}
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<Color&>(cb) == "BLUE");
REQUIRE(enum_name(cm[1]) == "GREEN");
REQUIRE(enum_name(Color::RED | Color{0}) == "RED");
REQUIRE(enum_name(Color::RED | Color::GREEN).empty());
REQUIRE(enum_name(Color::RED | Color{8}).empty());
REQUIRE(enum_name(static_cast<Color>(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::three) == "three");
REQUIRE(enum_name(Numbers::many) == "many");
REQUIRE(enum_name(Numbers::many | Numbers::two).empty());
REQUIRE(enum_name(static_cast<Numbers>(0)).empty());
constexpr Directions dr = Directions::Right;
constexpr auto dr_name = enum_name(dr);
Directions du = Directions::Up;
REQUIRE(enum_name<Directions&>(du) == "Up");
REQUIRE(enum_name<const Directions>(Directions::Down) == "Down");
REQUIRE(dr_name == "Right");
REQUIRE(enum_name(Directions::Left) == "Left");
REQUIRE(enum_name(Directions::Right | Directions::Up | Directions::Left | Directions::Down).empty());
REQUIRE(enum_name(static_cast<Directions>(0)).empty());
constexpr number nto = number::three | number::one;
constexpr auto nto_name = enum_name(nto);
REQUIRE(enum_name(number::one) == "one");
REQUIRE(enum_name(number::two) == "two");
REQUIRE(enum_name(number::three) == "three");
REQUIRE(enum_name(number::four) == "four");
REQUIRE(nto_name.empty());
REQUIRE(enum_name(static_cast<number>(0)).empty());
}
}
TEST_CASE("enum_flags_name") {
constexpr Color cr = Color::RED;
auto cr_name = enum_flags_name(cr);
Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE};
Color cb = Color::BLUE;
REQUIRE(cr_name == "RED");
REQUIRE(enum_flags_name<Color&>(cb) == "BLUE");
REQUIRE(enum_flags_name(cm[1]) == "GREEN");
REQUIRE(enum_flags_name(Color::RED | Color{0}) == "RED");
REQUIRE(enum_flags_name(Color::RED | Color::GREEN) == "RED|GREEN");
REQUIRE(enum_flags_name(Color::RED | Color{8}).empty());
REQUIRE(enum_flags_name(static_cast<Color>(0)).empty());
constexpr Numbers no = Numbers::one;
auto no_name = enum_flags_name(no);
REQUIRE(no_name == "one");
REQUIRE(enum_flags_name(Numbers::two) == "two");
REQUIRE(enum_flags_name(Numbers::three) == "three");
REQUIRE(enum_flags_name(Numbers::many) == "many");
REQUIRE(enum_flags_name(Numbers::many | Numbers::two) == "two|many");
REQUIRE(enum_flags_name(static_cast<Numbers>(0)).empty());
constexpr Directions dr = Directions::Right;
auto dr_name = enum_flags_name(dr);
Directions du = Directions::Up;
REQUIRE(enum_flags_name<Directions&>(du) == "Up");
REQUIRE(enum_flags_name<const Directions>(Directions::Down) == "Down");
REQUIRE(dr_name == "Right");
REQUIRE(enum_flags_name(Directions::Left) == "Left");
REQUIRE(enum_flags_name(Directions::Right | Directions::Up | Directions::Left | Directions::Down) == "Left|Down|Up|Right");
REQUIRE(enum_flags_name(static_cast<Directions>(0)).empty());
constexpr number nto = number::three | number::one;
auto nto_name = enum_flags_name(nto);
REQUIRE(enum_flags_name(number::one) == "one");
REQUIRE(enum_flags_name(number::two) == "two");
REQUIRE(enum_flags_name(number::three) == "three");
REQUIRE(enum_flags_name(number::four) == "four");
REQUIRE(nto_name == "one|three");
REQUIRE(enum_flags_name(static_cast<number>(0)).empty());
}
TEST_CASE("enum_names") {
REQUIRE(std::is_same_v<decltype(enum_names<Color>()), const std::array<std::string_view, 3>&>);
constexpr auto& s1 = enum_names<Color&>();
REQUIRE(s1 == std::array<std::string_view, 3>{{"RED", "GREEN", "BLUE"}});
constexpr auto& s2 = enum_names<Numbers>();
REQUIRE(s2 == std::array<std::string_view, 4>{{"one", "two", "three", "many"}});
constexpr auto& s3 = enum_names<const Directions>();
REQUIRE(s3 == std::array<std::string_view, 4>{{"Left", "Down", "Up", "Right"}});
constexpr auto& s4 = enum_names<number>();
REQUIRE(s4 == std::array<std::string_view, 4>{{"one", "two", "three", "four"}});
}
TEST_CASE("enum_entries") {
REQUIRE(std::is_same_v<decltype(enum_entries<Color>()), const std::array<std::pair<Color, std::string_view>, 3>&>);
constexpr auto& s1 = enum_entries<Color&>();
REQUIRE(s1 == std::array<std::pair<Color, std::string_view>, 3>{{{Color::RED, "RED"}, {Color::GREEN, "GREEN"}, {Color::BLUE, "BLUE"}}});
constexpr auto& s2 = enum_entries<Numbers>();
REQUIRE(s2 == std::array<std::pair<Numbers, std::string_view>, 4>{{{Numbers::one, "one"}, {Numbers::two, "two"}, {Numbers::three, "three"}, {Numbers::many, "many"}}});
constexpr auto& s3 = enum_entries<Directions&>();
REQUIRE(s3 == std::array<std::pair<Directions, std::string_view>, 4>{{{Directions::Left, "Left"}, {Directions::Down, "Down"}, {Directions::Up, "Up"}, {Directions::Right, "Right"}}});
constexpr auto& s4 = enum_entries<number>();
REQUIRE(s4 == std::array<std::pair<number, std::string_view>, 4>{{{number::one, "one"}, {number::two, "two"}, {number::three, "three"}, {number::four, "four"}}});
}
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.str() == name);
};
test_ostream(std::make_optional(Color::RED), "RED");
test_ostream(Color::GREEN, "GREEN");
test_ostream(Color::BLUE, "BLUE");
test_ostream(Color::BLUE | Color::RED, "RED|BLUE");
test_ostream(Color::BLUE | Color::RED | Color::RED, "RED|BLUE");
test_ostream(static_cast<Color>(0), "0");
test_ostream(std::make_optional(static_cast<Color>(0)), "0");
test_ostream(std::make_optional(Numbers::one), "one");
test_ostream(Numbers::two, "two");
test_ostream(Numbers::three, "three");
test_ostream(Numbers::many, "many");
test_ostream(static_cast<Numbers>(0), "0");
test_ostream(std::make_optional(static_cast<Numbers>(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(Directions::Right | Directions::Left, "Left|Right");
test_ostream(static_cast<Directions>(0), "0");
test_ostream(std::make_optional(static_cast<Directions>(0)), "0");
test_ostream(std::make_optional(number::one), "one");
test_ostream(number::two, "two");
test_ostream(number::three, "three");
test_ostream(number::four, "four");
test_ostream(number::four | number::one, "one|four");
test_ostream(static_cast<number>(0), "0");
test_ostream(std::make_optional(static_cast<number>(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<decltype(e)> v;
ss >> v;
REQUIRE(v == e);
REQUIRE(ss);
};
test_istream(Color::GREEN, "GREEN");
test_istream(Color::BLUE, "BLUE");
test_istream(Color::BLUE | Color::RED, "RED|BLUE");
test_istream(Color::BLUE | Color::RED | Color::RED, "RED|BLUE");
test_istream(Numbers::two, "two");
test_istream(Numbers::three, "three");
test_istream(Numbers::many, "many");
test_istream(Directions::Down, "Down");
test_istream(Directions::Right, "Right");
test_istream(Directions::Left, "Left");
test_istream(Directions::Right | Directions::Left, "Left|Right");
test_istream(number::two, "two");
test_istream(number::three, "three");
test_istream(number::four, "four");
test_istream(number::four | number::one, "one|four");
}
TEST_CASE("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)));
}
}
#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 <auto Start, auto End, auto Inc, class F>
constexpr void constexpr_for(F&& f) {
if constexpr (Start < End) {
f(std::integral_constant<decltype(Start), Start>());
constexpr_for<Start + Inc, End, Inc>(f);
}
}
template <typename E, E V>
struct Foo {};
TEST_CASE("constexpr_for") {
constexpr_for<0, magic_enum::enum_count<Color>(), 1>([](auto i) {
[[maybe_unused]] Foo<Color, magic_enum::enum_value<Color, i>()> bar{};
});
}
#endif
#if defined(__cpp_lib_format)
#include <magic_enum/magic_enum_format.hpp>
TEST_CASE("format-base") {
REQUIRE(std::format("Test-{:~^11}.", Color::RED | Color::GREEN) == "Test-~RED|GREEN~.");
}
#endif
TEST_CASE("enum_flags_test") {
REQUIRE(enum_flags_test(Color::RED|Color::GREEN, Color::RED));
REQUIRE_FALSE(enum_flags_test(Color::RED|Color::GREEN, Color::BLUE));
REQUIRE_FALSE(enum_flags_test(Numbers::none, Numbers::none));
REQUIRE_FALSE(enum_flags_test(Numbers::none, Numbers::one));
REQUIRE(enum_flags_test(Numbers::one|Numbers::two|Numbers::many, Numbers::many));
REQUIRE_FALSE(enum_flags_test(Numbers::one|Numbers::two|Numbers::many, Numbers::three));
REQUIRE_FALSE(enum_flags_test(Numbers::one|Numbers::two|Numbers::many, Numbers::none));
REQUIRE_FALSE(enum_flags_test(Left|Right, NoDirection));
REQUIRE(enum_flags_test(Left|Right|Up|Down, Right));
REQUIRE_FALSE(enum_flags_test(Left|Up|Down, Right));
REQUIRE(enum_flags_test(number::one|number::two|number::four, number::one));
REQUIRE_FALSE(enum_flags_test(number::one|number::two|number::four, number::three));
REQUIRE_FALSE(enum_flags_test(number::one|number::two|number::four, number::no_number));
}
TEST_CASE("enum_flags_test_any") {
REQUIRE(enum_flags_test_any(Color::RED|Color::GREEN, Color::RED));
REQUIRE_FALSE(enum_flags_test_any(Color::RED|Color::GREEN, Color::BLUE));
REQUIRE_FALSE(enum_flags_test_any(Numbers::none, Numbers::none));
REQUIRE_FALSE(enum_flags_test_any(Numbers::none, Numbers::one));
REQUIRE(enum_flags_test_any(Numbers::one|Numbers::two|Numbers::many, Numbers::many));
REQUIRE_FALSE(enum_flags_test_any(Numbers::one|Numbers::two|Numbers::many, Numbers::three));
REQUIRE_FALSE(enum_flags_test_any(Numbers::one|Numbers::two|Numbers::many, Numbers::none));
REQUIRE_FALSE(enum_flags_test_any(Left|Right, NoDirection));
REQUIRE(enum_flags_test_any(Left|Right|Up|Down, Right));
REQUIRE_FALSE(enum_flags_test_any(Left|Up|Down, Right));
REQUIRE(enum_flags_test_any(number::one|number::two|number::four, number::one));
REQUIRE(enum_flags_test_any(number::one|number::two|number::four, number::one|number::two));
REQUIRE_FALSE(enum_flags_test_any(number::one|number::two|number::four, number::three));
REQUIRE_FALSE(enum_flags_test_any(number::one|number::two|number::four, number::no_number));
REQUIRE(enum_flags_test(Numbers::none, Numbers::none) == enum_flags_test_any(Numbers::none, Numbers::none));
REQUIRE(enum_flags_test(Numbers::one, Numbers::none) == enum_flags_test_any(Numbers::one, Numbers::none));
REQUIRE(enum_flags_test(Numbers::none, Numbers::one) == enum_flags_test_any(Numbers::none, Numbers::one));
}
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);
}
+445
View File
@@ -0,0 +1,445 @@
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2024 Daniil Goncharov <neargye@gmail.com>.
//
// 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 <catch2/catch.hpp>
#undef MAGIC_ENUM_RANGE_MIN
#define MAGIC_ENUM_RANGE_MIN -120
#undef MAGIC_ENUM_RANGE_MAX
#define MAGIC_ENUM_RANGE_MAX 120
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_fuse.hpp>
#include <magic_enum/magic_enum_iostream.hpp>
#include <array>
#include <cctype>
#include <string_view>
#include <sstream>
enum class Language : int { = 10, = 20, English = 30, 😃 = 40, TVÅ = 50 };
enum class LanguageFlag : int {
= 1 << 1,
= 1 << 2,
English = 1 << 3,
😃 = 1 << 4
};
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 lang = enum_cast<Language>("日本語");
REQUIRE(enum_cast<Language&>("한국어").value() == Language::);
REQUIRE(enum_cast<const Language>("English").value() == Language::English);
REQUIRE(lang.value() == Language::);
REQUIRE(enum_cast<Language>("😃").value() == Language::😃);
REQUIRE(enum_cast<Language>("TVÅ").value() == Language::TVÅ);
REQUIRE_FALSE(enum_cast<Language>("Französisch").has_value());
}
SECTION("integer") {
constexpr auto lang = enum_cast<Language>(10);
REQUIRE(enum_cast<Language&>(20).value() == Language::);
REQUIRE(enum_cast<const Language>(30).value() == Language::English);
REQUIRE(lang.value() == Language::);
REQUIRE(enum_cast<Language>(40).value() == Language::😃);
REQUIRE_FALSE(enum_cast<Language>(0).has_value());
}
}
TEST_CASE("enum_integer") {
constexpr auto lang = enum_integer(Language::);
Language korean = Language::;
REQUIRE(enum_integer<Language&>(korean) == 20);
REQUIRE(enum_integer<const Language>(Language::English) == 30);
REQUIRE(enum_integer(Language::😃) == 40);
REQUIRE(lang == 10);
REQUIRE(enum_integer(static_cast<Language>(0)) == 0);
}
TEST_CASE("enum_index") {
constexpr auto lang = enum_index<Language>(Language::);
Language korean = Language::;
REQUIRE(enum_index<Language&>(korean) == 1);
REQUIRE(enum_index<const Language>(Language::English).value() == 2);
REQUIRE(enum_index(Language::😃) == 3);
REQUIRE(lang.value() == 0);
REQUIRE_FALSE(enum_index(static_cast<Language>(0)).has_value());
}
TEST_CASE("enum_contains") {
SECTION("value") {
constexpr auto lang = enum_contains(Language::);
Language korean = Language::;
REQUIRE(enum_contains<Language&>(korean));
REQUIRE(enum_contains<const Language>(Language::English));
REQUIRE(enum_contains(Language::😃));
REQUIRE(lang);
}
SECTION("integer") {
constexpr auto lang = enum_integer(Language::);
REQUIRE(enum_contains<Language&>(lang));
REQUIRE(enum_contains<const Language>(Language::));
REQUIRE(enum_contains<Language>(Language::😃));
REQUIRE_FALSE(enum_contains<Language>(static_cast<Language>(0)));
}
SECTION("string") {
auto lang = std::string{"日本語"};
REQUIRE(enum_contains<Language&>("한국어"));
REQUIRE(enum_contains<Language>("English"));
REQUIRE(enum_contains<const Language>(lang));
REQUIRE(enum_contains<Language>("😃"));
REQUIRE_FALSE(enum_contains<Language>("None"));
}
}
TEST_CASE("enum_value") {
constexpr auto lang = enum_value<Language>(3);
REQUIRE(enum_value<Language&>(0) == Language::);
REQUIRE(enum_value<const Language>(1) == Language::);
REQUIRE(enum_value<Language>(2) == Language::English);
REQUIRE(lang == Language::😃);
}
TEST_CASE("enum_values") {
constexpr auto& s7 = enum_values<const Language>();
REQUIRE(s7 == std::array<Language, 5>{{Language::, Language::, Language::English, Language::😃, Language::TVÅ}});
}
TEST_CASE("enum_count") {
constexpr auto s7 = enum_count<Language>();
REQUIRE(s7 == 5);
}
TEST_CASE("enum_name") {
SECTION("automatic storage") {
constexpr Language lang = Language::;
constexpr auto lang_name = enum_name(lang);
Language lk = Language::;
REQUIRE(enum_name<Language&>(lk) == "한국어");
REQUIRE(enum_name<const Language>(Language::English) == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_name(Language::😃) == "😃");
REQUIRE(enum_name(Language::TVÅ) == "TVÅ");
REQUIRE(enum_name(static_cast<Language>(0)).empty());
}
SECTION("static storage") {
constexpr Language lang = Language::;
constexpr auto lang_name = enum_name<lang>();
REQUIRE(enum_name<Language::>() == "한국어");
REQUIRE(enum_name<Language::English>() == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_name<Language::😃>() == "😃");
}
}
TEST_CASE("enum_names") {
constexpr auto& s5 = enum_names<const Language>();
REQUIRE(s5 == std::array<std::string_view, 5>{{"日本語", "한국어", "English", "😃", "TVÅ"}});
}
TEST_CASE("enum_entries") {
constexpr auto& s5 = enum_entries<const Language>();
REQUIRE(s5 == std::array<std::pair<Language, std::string_view>, 5>{{{Language::, "日本語"}, {Language::, "한국어"}, {Language::English, "English"}, {Language::😃, "😃"}, {Language::TVÅ, "TVÅ"}}});
}
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(Language::), "日本語");
test_ostream(Language::, "한국어");
test_ostream(Language::English, "English");
test_ostream(Language::😃, "😃");
test_ostream(static_cast<Language>(0), "0");
test_ostream(std::make_optional(static_cast<Language>(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<decltype(e)> v;
ss >> v;
REQUIRE(ss);
REQUIRE(v == e);
};
test_istream(Language::, "한국어");
test_istream(Language::English, "English");
test_istream(Language::😃, "😃");
}
TEST_CASE("bitwise_operators") {
using namespace magic_enum::bitwise_operators;
SECTION("operator^") {
REQUIRE(enum_integer(~Language::) == ~enum_integer(Language::));
}
SECTION("operator|") {
REQUIRE(enum_integer(Language:: | Language::) == (enum_integer(Language::) | enum_integer(Language::)));
}
SECTION("operator&") {
REQUIRE(enum_integer(Language:: & Language::) == (enum_integer(Language::) & enum_integer(Language::)));
}
SECTION("operator^") {
REQUIRE(enum_integer(Language:: ^ Language::) == (enum_integer(Language::) ^ enum_integer(Language::)));
}
SECTION("operator|=") {
Language x5 = Language::;
x5 |= Language::;
REQUIRE(enum_integer(x5) == (enum_integer(Language::) | enum_integer(Language::)));
}
SECTION("operator&=") {
Language x5 = Language::;
x5 &= Language::;
REQUIRE(enum_integer(x5) == (enum_integer(Language::) & enum_integer(Language::)));
}
SECTION("operator^=") {
Language x5 = Language::;
x5 ^= Language::;
REQUIRE(enum_integer(x5) == (enum_integer(Language::) ^ enum_integer(Language::)));
}
}
TEST_CASE("type_traits") {
REQUIRE_FALSE(is_unscoped_enum_v<Language>);
}
TEST_CASE("enum_type_name") {
REQUIRE(enum_type_name<const Language&>() == "Language");
}
TEST_CASE("extrema") {
SECTION("min") {
REQUIRE(magic_enum::customize::enum_range<Language>::min == MAGIC_ENUM_RANGE_MIN);
REQUIRE(magic_enum::detail::reflected_min<Language, as_common<>>() == MAGIC_ENUM_RANGE_MIN);
REQUIRE(magic_enum::detail::min_v<Language, as_common<>> == 10);
}
SECTION("max") {
REQUIRE(magic_enum::customize::enum_range<Language>::max == MAGIC_ENUM_RANGE_MAX);
REQUIRE(magic_enum::detail::reflected_max<Language, as_common<>>() == MAGIC_ENUM_RANGE_MAX);
REQUIRE(magic_enum::detail::max_v<Language, as_common<>> == 50);
}
}
/* LanguageFlag tests */
TEST_CASE("flag enum_cast") {
SECTION("string") {
constexpr auto lang = enum_cast<LanguageFlag>("日本語");
REQUIRE(enum_cast<LanguageFlag&>("한국어").value() == LanguageFlag::);
REQUIRE(enum_cast<const LanguageFlag>("English").value() == LanguageFlag::English);
REQUIRE(lang.value() == LanguageFlag::);
REQUIRE(enum_cast<LanguageFlag>("😃").value() == LanguageFlag::😃);
REQUIRE_FALSE(enum_cast<LanguageFlag>("None").has_value());
}
SECTION("integer") {
constexpr auto lang = enum_cast<LanguageFlag>(1 << 1);
REQUIRE(enum_cast<LanguageFlag&>(1 << 2).value() == LanguageFlag::);
REQUIRE(enum_cast<const LanguageFlag>(1 << 3).value() == LanguageFlag::English);
REQUIRE(lang.value() == LanguageFlag::);
REQUIRE(enum_cast<LanguageFlag>(1 << 4).value() == LanguageFlag::😃);
REQUIRE_FALSE(enum_cast<LanguageFlag>(0).has_value());
}
}
TEST_CASE("flag enum_index") {
constexpr auto lang = enum_index<LanguageFlag>(LanguageFlag::);
LanguageFlag korean = LanguageFlag::;
REQUIRE(enum_index<LanguageFlag&>(korean).value() == 1);
REQUIRE(enum_index<const LanguageFlag>(LanguageFlag::English).value() == 2);
REQUIRE(enum_index(LanguageFlag::😃).value() == 3);
REQUIRE(lang.value() == 0);
REQUIRE_FALSE(enum_index(static_cast<LanguageFlag>(0)).has_value());
}
TEST_CASE("flag enum_contains") {
SECTION("value") {
constexpr auto lang = enum_index<LanguageFlag>(LanguageFlag::);
LanguageFlag korean = LanguageFlag::;
REQUIRE(enum_contains<LanguageFlag&>(korean));
REQUIRE(enum_contains<const LanguageFlag>(LanguageFlag::English));
REQUIRE(enum_contains(LanguageFlag::😃));
REQUIRE(lang);
REQUIRE_FALSE(enum_contains(static_cast<LanguageFlag>(0)));
}
SECTION("integer") {
constexpr auto lang = enum_contains<LanguageFlag&>(1 << 1);
REQUIRE(lang);
REQUIRE(enum_contains<const LanguageFlag>(1 << 2));
REQUIRE(enum_contains<LanguageFlag>(1 << 3));
REQUIRE(enum_contains<LanguageFlag>(1 << 4));
REQUIRE_FALSE(enum_contains(static_cast<LanguageFlag>(0)));
}
SECTION("string") {
auto lang = std::string{"日本語"};
REQUIRE(enum_contains<LanguageFlag&>("한국어"));
REQUIRE(enum_contains<LanguageFlag>("English"));
REQUIRE(enum_contains<const LanguageFlag>(lang));
REQUIRE(enum_contains<LanguageFlag>("😃"));
REQUIRE_FALSE(enum_contains<LanguageFlag>("None"));
}
}
TEST_CASE("flag enum_value") {
constexpr auto lang = enum_value<LanguageFlag>(3);
REQUIRE(enum_value<LanguageFlag&>(0) == LanguageFlag::);
REQUIRE(enum_value<const LanguageFlag>(1) == LanguageFlag::);
REQUIRE(enum_value<LanguageFlag>(2) == LanguageFlag::English);
REQUIRE(lang == LanguageFlag::😃);
}
TEST_CASE("flag enum_values") {
constexpr auto& s5 = enum_values<const LanguageFlag>();
REQUIRE(s5 == std::array<LanguageFlag, 4>{{LanguageFlag::, LanguageFlag::, LanguageFlag::English, LanguageFlag::😃}});
}
TEST_CASE("flag enum_count") {
constexpr auto s5 = enum_count<LanguageFlag>();
REQUIRE(s5 == 4);
}
TEST_CASE("flag enum_name") {
SECTION("automatic storage") {
constexpr LanguageFlag lang = LanguageFlag::;
constexpr auto lang_name = enum_name(lang);
LanguageFlag lk = LanguageFlag::;
REQUIRE(enum_name<LanguageFlag&>(lk) == "한국어");
REQUIRE(enum_name<const LanguageFlag>(LanguageFlag::English) == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_name(LanguageFlag::😃) == "😃");
REQUIRE(enum_name(static_cast<LanguageFlag>(0)).empty());
}
}
TEST_CASE("flag enum_flags_name") {
constexpr LanguageFlag lang = LanguageFlag::;
auto lang_name = enum_flags_name(lang);
LanguageFlag lk = LanguageFlag::;
REQUIRE(enum_flags_name<LanguageFlag&>(lk) == "한국어");
REQUIRE(enum_flags_name<const LanguageFlag>(LanguageFlag::English) == "English");
REQUIRE(lang_name == "日本語");
REQUIRE(enum_flags_name(LanguageFlag::😃) == "😃");
REQUIRE(enum_flags_name(static_cast<LanguageFlag>(0)).empty());
}
TEST_CASE("flag enum_names") {
constexpr auto& s5 = enum_names<const LanguageFlag>();
REQUIRE(s5 == std::array<std::string_view, 4>{{"日本語", "한국어", "English", "😃"}});
}
TEST_CASE("flag enum_entries") {
constexpr auto& s5 = enum_entries<const LanguageFlag>();
REQUIRE(s5 == std::array<std::pair<LanguageFlag, std::string_view>, 4>{{{LanguageFlag::, "日本語"}, {LanguageFlag::, "한국어"}, {LanguageFlag::English, "English"}, {LanguageFlag::😃, "😃"}}});
}
TEST_CASE("flag ostream_operators") {
auto test_ostream = [](auto e, std::string name) {
using namespace magic_enum::ostream_operators;
std::stringstream ss;
ss << e;
REQUIRE(ss.str() == name);
};
test_ostream(std::make_optional(LanguageFlag::), "日本語");
test_ostream(LanguageFlag::, "한국어");
test_ostream(LanguageFlag::English, "English");
test_ostream(LanguageFlag::😃, "😃");
test_ostream(static_cast<LanguageFlag>(0), "0");
test_ostream(std::make_optional(static_cast<LanguageFlag>(0)), "0");
}
TEST_CASE("flag istream_operators") {
auto test_istream = [](const auto e, std::string name) {
using namespace magic_enum::istream_operators;
std::istringstream ss(name);
std::decay_t<decltype(e)> v;
ss >> v;
REQUIRE(v == e);
REQUIRE(ss);
};
test_istream(LanguageFlag::, "한국어");
test_istream(LanguageFlag::English, "English");
test_istream(LanguageFlag::😃, "😃");
}
TEST_CASE("flag bitwise_operators") {
using namespace magic_enum::bitwise_operators;
SECTION("operator~") {
REQUIRE(enum_integer(~LanguageFlag::) == ~enum_integer(LanguageFlag::));
}
SECTION("operator|") {
REQUIRE(enum_integer(LanguageFlag:: | LanguageFlag::) == (enum_integer(LanguageFlag::) | enum_integer(LanguageFlag::)));
}
SECTION("operator&") {
REQUIRE(enum_integer(LanguageFlag:: & LanguageFlag::) == (enum_integer(LanguageFlag::) & enum_integer(LanguageFlag::)));
}
SECTION("operator^") {
REQUIRE(enum_integer(LanguageFlag:: ^ LanguageFlag::) == (enum_integer(LanguageFlag::) ^ enum_integer(LanguageFlag::)));
}
SECTION("operator|=") {
LanguageFlag x5 = LanguageFlag::;
x5 |= LanguageFlag::;
REQUIRE(enum_integer(x5) == (enum_integer(LanguageFlag::) | enum_integer(LanguageFlag::)));
}
SECTION("operator&=") {
LanguageFlag x5 = LanguageFlag::;
x5 &= LanguageFlag::;
REQUIRE(enum_integer(x5) == (enum_integer(LanguageFlag::) & enum_integer(LanguageFlag::)));
}
SECTION("operator^=") {
LanguageFlag x5 = LanguageFlag::;
x5 ^= LanguageFlag::;
REQUIRE(enum_integer(x5) == (enum_integer(LanguageFlag::) ^ enum_integer(LanguageFlag::)));
}
}
+147
View File
@@ -0,0 +1,147 @@
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 - 2024 Daniil Goncharov <neargye@gmail.com>.
//
// 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 <catch2/catch.hpp>
#define MAGIC_ENUM_USING_ALIAS_STRING_VIEW using string_view = std::wstring_view;
#define MAGIC_ENUM_USING_ALIAS_STRING using string = std::wstring;
#include <magic_enum/magic_enum.hpp>
#include <magic_enum/magic_enum_iostream.hpp>
#include <array>
#include <cctype>
#include <string_view>
#include <sstream>
enum class Color { RED = -12, GREEN = 7, BLUE = 15 };
template <>
constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<Color>(Color value) noexcept {
switch (value) {
case Color::RED:
return L"red";
default:
return default_tag;
}
}
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<Color>(L"red");
REQUIRE(cr.value() == Color::RED);
REQUIRE(enum_cast<Color&>(L"GREEN").value() == Color::GREEN);
REQUIRE(enum_cast<Color>(L"blue", [](wchar_t lhs, wchar_t rhs) { return std::tolower(lhs) == std::tolower(rhs); }).value() == Color::BLUE);
REQUIRE_FALSE(enum_cast<Color>(L"None").has_value());
}
SECTION("integer") {
Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE};
constexpr auto cr = enum_cast<Color>(-12);
REQUIRE(cr.value() == Color::RED);
REQUIRE(enum_cast<Color&>(7).value() == Color::GREEN);
REQUIRE(enum_cast<Color>(static_cast<int>(cm[2])).value() == Color::BLUE);
REQUIRE_FALSE(enum_cast<Color>(0).has_value());
}
}
TEST_CASE("enum_values") {
REQUIRE(std::is_same_v<decltype(enum_values<Color>()), const std::array<Color, 3>&>);
constexpr auto& s1 = enum_values<Color&>();
REQUIRE(s1 == std::array<Color, 3>{{Color::RED, Color::GREEN, Color::BLUE}});
}
TEST_CASE("enum_count") {
constexpr auto s1 = enum_count<Color&>();
REQUIRE(s1 == 3);
}
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 == L"red");
REQUIRE(enum_name<Color&>(cb) == L"BLUE");
REQUIRE(enum_name<as_flags<false>>(cm[1]) == L"GREEN");
REQUIRE(enum_name<as_common<true>>(cm[1]) == L"GREEN");
REQUIRE(enum_name<as_flags<false>>(static_cast<Color>(0)).empty());
}
SECTION("static storage") {
constexpr Color cr = Color::RED;
constexpr auto cr_name = enum_name<cr>();
constexpr Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE};
REQUIRE(cr_name == L"red");
REQUIRE(enum_name<Color::BLUE>() == L"BLUE");
REQUIRE(enum_name<cm[1]>() == L"GREEN");
}
}
TEST_CASE("enum_names") {
REQUIRE(std::is_same_v<decltype(enum_names<Color>()), const std::array<std::wstring_view, 3>&>);
constexpr auto& s1 = enum_names<Color&>();
REQUIRE(s1 == std::array<std::wstring_view, 3>{{L"red", L"GREEN", L"BLUE"}});
}
TEST_CASE("enum_entries") {
REQUIRE(std::is_same_v<decltype(enum_entries<Color>()), const std::array<std::pair<Color, std::wstring_view>, 3>&>);
constexpr auto& s1 = enum_entries<Color&>();
REQUIRE(s1 == std::array<std::pair<Color, std::wstring_view>, 3>{{{Color::RED, L"red"}, {Color::GREEN, L"GREEN"}, {Color::BLUE, L"BLUE"}}});
}
TEST_CASE("ostream_operators") {
auto test_ostream = [](auto e, std::wstring name) {
using namespace magic_enum::ostream_operators;
std::wstringstream ss;
ss << e;
REQUIRE(ss);
REQUIRE(ss.str() == name);
};
test_ostream(std::make_optional(Color::RED), L"red");
test_ostream(Color::GREEN, L"GREEN");
test_ostream(Color::BLUE, L"BLUE");
test_ostream(static_cast<Color>(0), L"0");
test_ostream(std::make_optional(static_cast<Color>(0)), L"0");
}
TEST_CASE("istream_operators") {
auto test_istream = [](const auto e, std::wstring name) {
using namespace magic_enum::istream_operators;
std::wistringstream ss(name);
std::decay_t<decltype(e)> v;
ss >> v;
REQUIRE(ss);
REQUIRE(v == e);
};
test_istream(Color::GREEN, L"GREEN");
test_istream(Color::BLUE, L"BLUE");
}