初始化内容
This commit is contained in:
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import %workspace%/../.bazelrc
|
||||
|
||||
+23
@@ -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
Vendored
+25
@@ -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"],
|
||||
)
|
||||
Vendored
+126
@@ -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()
|
||||
Vendored
+6
@@ -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")
|
||||
Vendored
+17
@@ -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
|
||||
Vendored
+1288
File diff suppressed because it is too large
Load Diff
+137
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
Vendored
+834
@@ -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
@@ -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
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user