v01
This commit is contained in:
27
thirdparty/magic_enum/.github/workflows/macos.yml
vendored
Normal file
27
thirdparty/magic_enum/.github/workflows/macos.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: macos
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{matrix.config.os}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- { os: macos-10.15 }
|
||||
- { os: macos-11.0 }
|
||||
build: [Debug, Release]
|
||||
|
||||
name: "${{matrix.config.os}}:${{matrix.build}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -DCMAKE_BUILD_TYPE=${{matrix.build}}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build . --config ${{matrix.build}}
|
||||
|
||||
- name: Tests
|
||||
run: ctest --output-on-failure -C ${{matrix.build}}
|
||||
30
thirdparty/magic_enum/.github/workflows/ubuntu.yml
vendored
Normal file
30
thirdparty/magic_enum/.github/workflows/ubuntu.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: ubuntu
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ubuntu:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build: [Debug, Release]
|
||||
compiler:
|
||||
- { cc: "gcc-9", cxx: "g++-9" }
|
||||
- { cc: "gcc-10", cxx: "g++-10" }
|
||||
- { cc: "clang-10", cxx: "clang++-10" }
|
||||
- { cc: "clang-11", cxx: "clang++-11" }
|
||||
- { cc: "clang-12", cxx: "clang++-12" }
|
||||
|
||||
name: "${{matrix.compiler.cxx}}:${{matrix.build}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -DCMAKE_BUILD_TYPE=${{matrix.build}} -DCMAKE_C_COMPILER=${{matrix.compiler.cc}} -DCMAKE_CXX_COMPILER=${{matrix.compiler.cxx}}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build . --config ${{matrix.build}}
|
||||
|
||||
- name: Tests
|
||||
run: ctest --output-on-failure -C ${{matrix.build}}
|
||||
28
thirdparty/magic_enum/.github/workflows/windows.yml
vendored
Normal file
28
thirdparty/magic_enum/.github/workflows/windows.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: windows
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{matrix.config.os}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- { os: windows-2016, vs: "Visual Studio 2017" } # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2016-Readme.md#visual-studio-enterprise-2017
|
||||
- { os: windows-2019, vs: "Visual Studio 2019" } # https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#visual-studio-enterprise-2019
|
||||
build: [Debug, Release]
|
||||
platform: [Win32, x64]
|
||||
|
||||
name: "${{matrix.config.vs}}:${{matrix.platform}}:${{matrix.build}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -A ${{matrix.platform}}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build . --config ${{matrix.build}}
|
||||
|
||||
- name: Tests
|
||||
run: ctest --output-on-failure -C ${{matrix.build}}
|
||||
53
thirdparty/magic_enum/.gitignore
vendored
Normal file
53
thirdparty/magic_enum/.gitignore
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
build/
|
||||
.vscode/
|
||||
.vs/
|
||||
|
||||
### C++ gitignore ###
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
### CMake gitignore ###
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Testing
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
|
||||
### Bazel build artifacts ###
|
||||
/bazel-*
|
||||
63
thirdparty/magic_enum/BUILD.bazel
vendored
Normal file
63
thirdparty/magic_enum/BUILD.bazel
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
licenses(["notice"])
|
||||
|
||||
exports_files(["LICENSE"])
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_library(
|
||||
name = "magic_enum",
|
||||
hdrs = ["include/magic_enum.hpp"],
|
||||
includes = ["include"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "example",
|
||||
srcs = ["example/example.cpp"],
|
||||
copts = ["-std=c++17"],
|
||||
deps = [":magic_enum"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "enum_flag_example",
|
||||
srcs = ["example/enum_flag_example.cpp"],
|
||||
copts = ["-std=c++17"],
|
||||
deps = [":magic_enum"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "example_custom_name",
|
||||
srcs = ["example/example_custom_name.cpp"],
|
||||
copts = ["-std=c++17"],
|
||||
deps = [":magic_enum"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "catch",
|
||||
srcs = [],
|
||||
hdrs = ["test/3rdparty/Catch2/include/catch2/catch.hpp"],
|
||||
strip_include_prefix = "test/3rdparty/Catch2/include",
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "test",
|
||||
srcs = [
|
||||
"test/test.cpp",
|
||||
],
|
||||
copts = ["-std=c++17"],
|
||||
deps = [
|
||||
":catch",
|
||||
":magic_enum",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "test_flags",
|
||||
srcs = [
|
||||
"test/test_flags.cpp",
|
||||
],
|
||||
copts = ["-std=c++17"],
|
||||
deps = [
|
||||
":catch",
|
||||
":magic_enum",
|
||||
],
|
||||
)
|
||||
54
thirdparty/magic_enum/CMakeLists.txt
vendored
Normal file
54
thirdparty/magic_enum/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(magic_enum VERSION "0.7.3" LANGUAGES CXX)
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
set(IS_TOPLEVEL_PROJECT TRUE)
|
||||
else()
|
||||
set(IS_TOPLEVEL_PROJECT FALSE)
|
||||
endif()
|
||||
|
||||
option(MAGIC_ENUM_OPT_BUILD_EXAMPLES "Build magic_enum examples" ${IS_TOPLEVEL_PROJECT})
|
||||
option(MAGIC_ENUM_OPT_BUILD_TESTS "Build and perform magic_enum tests" ${IS_TOPLEVEL_PROJECT})
|
||||
option(MAGIC_ENUM_OPT_INSTALL "Generate and install magic_enum target" ${IS_TOPLEVEL_PROJECT})
|
||||
|
||||
if(MAGIC_ENUM_OPT_BUILD_EXAMPLES)
|
||||
add_subdirectory(example)
|
||||
endif()
|
||||
|
||||
if(MAGIC_ENUM_OPT_BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
|
||||
write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
ARCH_INDEPENDENT)
|
||||
|
||||
if(MAGIC_ENUM_OPT_INSTALL)
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
EXPORT ${PROJECT_NAME}Config)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
DESTINATION lib/cmake/${PROJECT_NAME})
|
||||
|
||||
install(EXPORT ${PROJECT_NAME}Config
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION lib/cmake/${PROJECT_NAME})
|
||||
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
DESTINATION .)
|
||||
|
||||
export(EXPORT ${PROJECT_NAME}Config
|
||||
NAMESPACE ${PROJECT_NAME}::)
|
||||
endif()
|
||||
21
thirdparty/magic_enum/LICENSE
vendored
Normal file
21
thirdparty/magic_enum/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 - 2021 Daniil Goncharov
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
250
thirdparty/magic_enum/README.md
vendored
Normal file
250
thirdparty/magic_enum/README.md
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
```text
|
||||
__ __ _ ______ _____
|
||||
| \/ | (_) | ____| / ____|_ _
|
||||
| \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
|
||||
| |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
|
||||
| | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
|
||||
|_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
|
||||
__/ |
|
||||
|___/
|
||||
```
|
||||
|
||||
[](https://github.com/Neargye/magic_enum/releases)
|
||||
[](https://conan.io/center/magic_enum)
|
||||
[](https://github.com/microsoft/vcpkg/tree/master/ports/magic-enum)
|
||||
[](https://www.cppget.org/magic_enum?q=magic_enum)
|
||||
[](LICENSE)
|
||||
[](https://wandbox.org/permlink/CmWdR9oPY4vhWYuH)
|
||||
[](https://godbolt.org/z/BxfmsH)
|
||||
|
||||
# Magic Enum C++
|
||||
|
||||
Header-only C++17 library provides static reflection for enums, work with any enum type without any macro or boilerplate code.
|
||||
|
||||
* `enum_cast` obtains enum value from string or integer.
|
||||
* `enum_value` returns enum value at specified index.
|
||||
* `enum_values` obtains enum value sequence.
|
||||
* `enum_count` returns number of enum values.
|
||||
* `enum_integer` obtains integer value from enum value.
|
||||
* `enum_name` returns name from enum value.
|
||||
* `enum_names` obtains string enum name sequence.
|
||||
* `enum_entries` obtains pair (value enum, string enum name) sequence.
|
||||
* `enum_index` obtains index in enum value sequence from enum value.
|
||||
* `enum_contains` checks whether enum contains enumerator with such value.
|
||||
* `enum_type_name` returns name of enum type.
|
||||
* `is_unscoped_enum` checks whether type is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration).
|
||||
* `is_scoped_enum` checks whether type is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations).
|
||||
* `underlying_type` improved UB-free "SFINAE-friendly" [underlying_type](https://en.cppreference.com/w/cpp/types/underlying_type).
|
||||
* `ostream_operators` ostream operators for enums.
|
||||
* `bitwise_operators` bitwise operators for enums.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Reference](doc/reference.md)
|
||||
* [Limitations](doc/limitations.md)
|
||||
* [Integration](#Integration)
|
||||
|
||||
## Features
|
||||
|
||||
* C++17
|
||||
* Header-only
|
||||
* Dependency-free
|
||||
* Compile-time
|
||||
* Enum to string
|
||||
* String to enum
|
||||
* Iterating over enum
|
||||
|
||||
## [Examples](example/example.cpp)
|
||||
|
||||
```cpp
|
||||
// For example color enum.
|
||||
enum class Color { RED = 2, BLUE = 4, GREEN = 8 };
|
||||
```
|
||||
|
||||
* Enum value to string
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto color_name = magic_enum::enum_name(color);
|
||||
// color_name -> "RED"
|
||||
```
|
||||
|
||||
* String to enum value
|
||||
|
||||
```cpp
|
||||
std::string color_name{"GREEN"};
|
||||
auto color = magic_enum::enum_cast<Color>(color_name);
|
||||
if (color.has_value()) {
|
||||
// color.value() -> Color::GREEN
|
||||
}
|
||||
```
|
||||
|
||||
* Integer to enum value
|
||||
|
||||
```cpp
|
||||
int color_integer = 2;
|
||||
auto color = magic_enum::enum_cast<Color>(color_integer);
|
||||
if (color.has_value()) {
|
||||
// color.value() -> Color::RED
|
||||
}
|
||||
```
|
||||
|
||||
* Indexed access to enum value
|
||||
|
||||
```cpp
|
||||
std::size_t i = 1;
|
||||
Color color = magic_enum::enum_value<Color>(i);
|
||||
// color -> Color::BLUE
|
||||
```
|
||||
|
||||
* Enum value sequence
|
||||
|
||||
```cpp
|
||||
constexpr auto& colors = magic_enum::enum_values<Color>();
|
||||
// colors -> {Color::RED, Color::BLUE, Color::GREEN}
|
||||
// colors[0] -> Color::RED
|
||||
```
|
||||
|
||||
* Number of enum elements
|
||||
|
||||
```cpp
|
||||
constexpr std::size_t color_count = magic_enum::enum_count<Color>();
|
||||
// color_count -> 3
|
||||
```
|
||||
|
||||
* Enum value to integer
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto color_integer = magic_enum::enum_integer(color);
|
||||
// color -> 2
|
||||
```
|
||||
|
||||
* Enum names sequence
|
||||
|
||||
```cpp
|
||||
constexpr auto& color_names = magic_enum::enum_names<Color>();
|
||||
// color_names -> {"RED", "BLUE", "GREEN"}
|
||||
// color_names[0] -> "RED"
|
||||
```
|
||||
|
||||
* Enum entries sequence
|
||||
|
||||
```cpp
|
||||
constexpr auto& color_entries = magic_enum::enum_entries<Color>();
|
||||
// color_entries -> {{Color::RED, "RED"}, {Color::BLUE, "BLUE"}, {Color::GREEN, "GREEN"}}
|
||||
// color_entries[0].first -> Color::RED
|
||||
// color_entries[0].second -> "RED"
|
||||
```
|
||||
|
||||
* Ostream operator for enum
|
||||
|
||||
```cpp
|
||||
using namespace magic_enum::ostream_operators; // out-of-the-box ostream operators for enums.
|
||||
Color color = Color::BLUE;
|
||||
std::cout << color << std::endl; // "BLUE"
|
||||
```
|
||||
|
||||
* Bitwise operator for enum
|
||||
|
||||
```cpp
|
||||
enum class Flags { A = 1 << 0, B = 1 << 1, C = 1 << 2, D = 1 << 3 };
|
||||
using namespace magic_enum::bitwise_operators; // out-of-the-box bitwise operators for enums.
|
||||
// Support operators: ~, |, &, ^, |=, &=, ^=.
|
||||
Flags flags = Flags::A | Flags::B & ~Flags::C;
|
||||
```
|
||||
|
||||
* Checks whether type is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration).
|
||||
|
||||
```cpp
|
||||
enum color { red, green, blue };
|
||||
enum class direction { left, right };
|
||||
|
||||
magic_enum::is_unscoped_enum<color>::value -> true
|
||||
magic_enum::is_unscoped_enum<direction>::value -> false
|
||||
magic_enum::is_unscoped_enum<int>::value -> false
|
||||
|
||||
// Helper variable template.
|
||||
magic_enum::is_unscoped_enum_v<color> -> true
|
||||
```
|
||||
|
||||
* Checks whether type is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations).
|
||||
|
||||
```cpp
|
||||
enum color { red, green, blue };
|
||||
enum class direction { left, right };
|
||||
|
||||
magic_enum::is_scoped_enum<color>::value -> false
|
||||
magic_enum::is_scoped_enum<direction>::value -> true
|
||||
magic_enum::is_scoped_enum<int>::value -> false
|
||||
|
||||
// Helper variable template.
|
||||
magic_enum::is_scoped_enum_v<direction> -> true
|
||||
```
|
||||
|
||||
* Static storage enum variable to string
|
||||
This version is much lighter on the compile times and is not restricted to the enum_range [limitation](doc/limitations.md).
|
||||
|
||||
```cpp
|
||||
constexpr Color color = Color::BLUE;
|
||||
constexpr auto color_name = magic_enum::enum_name<color>();
|
||||
// color_name -> "BLUE"
|
||||
```
|
||||
|
||||
## Remarks
|
||||
|
||||
* `magic_enum` does not pretend to be a silver bullet for reflection for enums, it was originally designed for small enum.
|
||||
|
||||
* Before use, read the [limitations](doc/limitations.md) of functionality.
|
||||
|
||||
* For the small enum use the API from the namespace `magic_enum`, and for enum-flags use the API from the namespace `magic_enum::flags`.
|
||||
|
||||
## Integration
|
||||
|
||||
* You should add the required file [magic_enum.hpp](include/magic_enum.hpp).
|
||||
|
||||
* If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can use the [magic-enum package](https://github.com/microsoft/vcpkg/tree/master/ports/magic-enum).
|
||||
|
||||
* If you are using [Conan](https://www.conan.io/) to manage your dependencies, merely add `magic_enum/x.y.z` to your conan's requires, where `x.y.z` is the release version you want to use.
|
||||
|
||||
* If you are using [Build2](https://build2.org/) to build and manage your dependencies, add `depends: magic_enum ^x.y.z` to the manifest file where `x.y.z` is the release version you want to use. You can then import the target using `magic_enum%lib{magic_enum}`.
|
||||
|
||||
* Alternatively, you can use something like [CPM](https://github.com/TheLartians/CPM) which is based on CMake's `Fetch_Content` module.
|
||||
|
||||
```cmake
|
||||
CPMAddPackage(
|
||||
NAME magic_enum
|
||||
GITHUB_REPOSITORY Neargye/magic_enum
|
||||
GIT_TAG x.y.z # Where `x.y.z` is the release version you want to use.
|
||||
)
|
||||
```
|
||||
|
||||
* Bazel is also supported, simply add to your WORKSPACE file:
|
||||
|
||||
```
|
||||
http_archive(
|
||||
name = "magic_enum",
|
||||
strip_prefix = "magic_enum-<commit>",
|
||||
urls = ["https://github.com/Neargye/magic_enum/archive/<commit>.zip"],
|
||||
)
|
||||
```
|
||||
|
||||
To use bazel inside the repository it's possible to do:
|
||||
|
||||
```
|
||||
bazel build //...
|
||||
bazel test //...
|
||||
bazel run //:example
|
||||
```
|
||||
|
||||
(Note that you must use a supported compiler or specify it with `export CC= <compiler>`.)
|
||||
|
||||
## Compiler compatibility
|
||||
|
||||
* Clang/LLVM >= 5
|
||||
* MSVC++ >= 14.11 / Visual Studio >= 2017
|
||||
* Xcode >= 10
|
||||
* GCC >= 9
|
||||
* MinGW >= 9
|
||||
|
||||
## Licensed under the [MIT License](LICENSE)
|
||||
0
thirdparty/magic_enum/WORKSPACE
vendored
Normal file
0
thirdparty/magic_enum/WORKSPACE
vendored
Normal file
109
thirdparty/magic_enum/doc/limitations.md
vendored
Normal file
109
thirdparty/magic_enum/doc/limitations.md
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
# Limitations
|
||||
|
||||
* This library uses a compiler-specific hack (based on `__PRETTY_FUNCTION__` / `__FUNCSIG__`), which works on Clang >= 5, MSVC >= 15.3 and GCC >= 9.
|
||||
|
||||
* To check is magic_enum supported compiler use macro `MAGIC_ENUM_SUPPORTED` or constexpr constant `magic_enum::is_magic_enum_supported`.</br>
|
||||
If magic_enum used on unsupported compiler, occurs the compilation error. To suppress error define macro `MAGIC_ENUM_NO_CHECK_SUPPORT`.
|
||||
|
||||
* Enum can't reflect if the enum is a forward declaration.
|
||||
|
||||
* Enum value must be in range `[MAGIC_ENUM_RANGE_MIN, MAGIC_ENUM_RANGE_MAX]`.
|
||||
|
||||
* By default `MAGIC_ENUM_RANGE_MIN = -128`, `MAGIC_ENUM_RANGE_MAX = 128`.
|
||||
|
||||
* `MAGIC_ENUM_RANGE_MIN` must be less or equals than `0` and must be greater than `INT16_MIN`.
|
||||
|
||||
* `MAGIC_ENUM_RANGE_MAX` must be greater than `0` and must be less than `INT16_MAX`.
|
||||
|
||||
* If need another range for all enum types by default, redefine the macro `MAGIC_ENUM_RANGE_MIN` and `MAGIC_ENUM_RANGE_MAX`.
|
||||
|
||||
```cpp
|
||||
#define MAGIC_ENUM_RANGE_MIN 0
|
||||
#define MAGIC_ENUM_RANGE_MAX 256
|
||||
#include <magic_enum.hpp>
|
||||
```
|
||||
|
||||
* If need another range for specific enum type, add specialization `enum_range` for necessary enum type. Specialization of `enum_range` must be injected in `namespace magic_enum::customize`.
|
||||
|
||||
```cpp
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
enum class number { one = 100, two = 200, three = 300 };
|
||||
|
||||
namespace magic_enum::customize {
|
||||
template <>
|
||||
struct enum_range<number> {
|
||||
static constexpr int min = 100; // Must be greater than `INT16_MIN`.
|
||||
static constexpr int max = 300; // Must be less than `INT16_MAX`.
|
||||
};
|
||||
} // namespace magic_enum
|
||||
```
|
||||
|
||||
* `magic_enum` [won't work if a value is aliased](https://github.com/Neargye/magic_enum/issues/68). Work with enum-aliases is compiler-implementation-defined.
|
||||
|
||||
```cpp
|
||||
enum ShapeKind {
|
||||
ConvexBegin = 0,
|
||||
Box = 0, // Won't work.
|
||||
Sphere = 1,
|
||||
ConvexEnd = 2,
|
||||
Donut = 2, // Won't work too.
|
||||
Banana = 3,
|
||||
COUNT = 4
|
||||
};
|
||||
// magic_enum::enum_cast<ShapeKind>("Box") -> nullopt
|
||||
// magic_enum::enum_name(ShapeKind::Box) -> "ConvexBegin"
|
||||
```
|
||||
|
||||
One of the possible workaround the issue:
|
||||
|
||||
```cpp
|
||||
enum ShapeKind {
|
||||
// Convex shapes, see ConvexBegin and ConvexEnd below.
|
||||
Box = 0,
|
||||
Sphere = 1,
|
||||
|
||||
// Non-convex shapes.
|
||||
Donut = 2,
|
||||
Banana = 3,
|
||||
|
||||
COUNT = Banana + 1,
|
||||
|
||||
// Non-reflected aliases.
|
||||
ConvexBegin = Box,
|
||||
ConvexEnd = Sphere + 1
|
||||
};
|
||||
// magic_enum::enum_cast<ShapeKind>("Box") -> ShapeKind::Box
|
||||
// magic_enum::enum_name(ShapeKind::Box) -> "Box"
|
||||
|
||||
// Non-reflected aliases.
|
||||
// magic_enum::enum_cast<ShapeKind>("ConvexBegin") -> nullopt
|
||||
// magic_enum::enum_name(ShapeKind::ConvexBegin) -> "Box"
|
||||
```
|
||||
|
||||
On some compiler enum-aliases not supported, [for example Visual Studio 2017](https://github.com/Neargye/magic_enum/issues/36), macro `MAGIC_ENUM_SUPPORTED_ALIASES` will be undefined.
|
||||
|
||||
```cpp
|
||||
enum Number {
|
||||
one = 1,
|
||||
ONE = 1
|
||||
};
|
||||
// magic_enum::enum_cast<Number>("one") -> nullopt
|
||||
// magic_enum::enum_name(Number::one) -> ""
|
||||
// magic_enum::enum_cast<Number>("ONE") -> nullopt
|
||||
// magic_enum::enum_name(Number::ONE) -> ""
|
||||
```
|
||||
|
||||
* If you hit a message like this:
|
||||
|
||||
```text
|
||||
[...]
|
||||
note: constexpr evaluation hit maximum step limit; possible infinite loop?
|
||||
```
|
||||
|
||||
Change the limit for the number of constexpr evaluated:
|
||||
* MSVC `/constexpr:depthN`, `/constexpr:stepsN` <https://docs.microsoft.com/en-us/cpp/build/reference/constexpr-control-constexpr-evaluation>
|
||||
* Clang `-fconstexpr-depth=N`, `-fconstexpr-steps=N` <https://clang.llvm.org/docs/UsersManual.html#controlling-implementation-limits>
|
||||
* GCC `-fconstexpr-depth=N`, `-fconstexpr-loop-limit=N`, `-fconstexpr-ops-limit=N` <https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/C_002b_002b-Dialect-Options.html>
|
||||
|
||||
* Intellisense Visual Studio may have some problems analyzing `magic_enum`.
|
||||
433
thirdparty/magic_enum/doc/reference.md
vendored
Normal file
433
thirdparty/magic_enum/doc/reference.md
vendored
Normal file
@@ -0,0 +1,433 @@
|
||||
# Reference
|
||||
|
||||
* [`enum_cast` obtains enum value from string or integer.](#enum_cast)
|
||||
* [`enum_value` returns enum value at specified index.](#enum_value)
|
||||
* [`enum_values` obtains enum value sequence.](#enum_values)
|
||||
* [`enum_count` returns number of enum values.](#enum_count)
|
||||
* [`enum_integer` obtains integer value from enum value.](#enum_integer)
|
||||
* [`enum_name` returns name from enum value.](#enum_name)
|
||||
* [`enum_names` obtains string enum name sequence.](#enum_names)
|
||||
* [`enum_entries` obtains pair (value enum, string enum name) sequence.](#enum_entries)
|
||||
* [`enum_index` obtains index in enum value sequence from enum value.](#enum_index)
|
||||
* [`enum_contains` checks whether enum contains enumerator with such value.](#enum_contains)
|
||||
* [`enum_type_name` returns type name of enum.](#enum_type_name)
|
||||
* [`is_unscoped_enum` checks whether type is an Unscoped enumeration.](#is_unscoped_enum)
|
||||
* [`is_scoped_enum` checks whether type is an Scoped enumeration.](#is_scoped_enum)
|
||||
* [`underlying_type` improved UB-free "SFINAE-friendly" underlying_type.](#underlying_type)
|
||||
* [`ostream_operators` ostream operators for enums.](#ostream_operators)
|
||||
* [`bitwise_operators` bitwise operators for enums.](#bitwise_operators)
|
||||
|
||||
## Synopsis
|
||||
|
||||
* Before use, read the [limitations](limitations.md) of functionality.
|
||||
|
||||
* To check is magic_enum supported compiler use macro `MAGIC_ENUM_SUPPORTED` or constexpr constant `magic_enum::is_magic_enum_supported`.</br>
|
||||
If magic_enum used on unsupported compiler, occurs the compilation error. To suppress error define macro `MAGIC_ENUM_NO_CHECK_SUPPORT`.
|
||||
|
||||
* For the small enum use the API from the namespace `magic_enum`, and for enum-flags use the API from the namespace `magic_enum::flags`.
|
||||
|
||||
* To add custom enum or type names see the [example](../example/example_custom_name.cpp).
|
||||
|
||||
* To change the type of strings or ortional, use special macros:
|
||||
|
||||
```cpp
|
||||
#include <my_lib/string.hpp>
|
||||
#include <my_lib/string_view.hpp>
|
||||
#define MAGIC_ENUM_USING_ALIAS_STRING using string = my_lib::String;
|
||||
#define MAGIC_ENUM_USING_ALIAS_STRING_VIEW using string_view = my_lib::StringView;
|
||||
#define MAGIC_ENUM_USING_ALIAS_OPTIONAL template <typename T> using optional = my_lib::Optional<T>;
|
||||
#include <magic_enum.hpp>
|
||||
```
|
||||
Optionally define `MAGIC_ENUM_CONFIG_FILE` i.e., in your build system, with path to header file with defined
|
||||
macros or constants, for example:
|
||||
|
||||
```cpp
|
||||
#define MAGIC_ENUM_CONFIG_FILE "my_magic_enum_cfg.hpp"
|
||||
```
|
||||
my_magic_enum_cfg.hpp:
|
||||
```cpp
|
||||
#include <my_lib/string.hpp>
|
||||
#include <my_lib/string_view.hpp>
|
||||
#define MAGIC_ENUM_USING_ALIAS_STRING using string = my_lib::String;
|
||||
#define MAGIC_ENUM_USING_ALIAS_STRING_VIEW using string_view = my_lib::StringView;
|
||||
#define MAGIC_ENUM_USING_ALIAS_OPTIONAL template <typename T> using optional = my_lib::Optional<T>;
|
||||
#define MAGIC_ENUM_RANGE_MIN 0
|
||||
#define MAGIC_ENUM_RANGE_MAX 255
|
||||
```
|
||||
|
||||
## `enum_cast`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr optional<E> enum_cast(underlying_type_t<E> value) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr optional<E> enum_cast(string_view value) noexcept;
|
||||
|
||||
template <typename E, typename BinaryPredicate>
|
||||
constexpr optional<E> enum_cast(string_view value, BinaryPredicate p) noexcept(is_nothrow_invocable_v<BinaryPredicate>);
|
||||
```
|
||||
|
||||
* Obtains enum value from string or integer.
|
||||
|
||||
* Returns `optional<E>`, using `has_value()` to check contains enum value and `value()` to get the enum value.
|
||||
|
||||
* If argument does not enum value, returns empty `optional`.
|
||||
|
||||
* Examples
|
||||
|
||||
* String to enum value.
|
||||
|
||||
```cpp
|
||||
string color_name{"GREEN"};
|
||||
auto color = magic_enum::enum_cast<Color>(color_name);
|
||||
if (color.has_value()) {
|
||||
// color.value() -> Color::GREEN
|
||||
}
|
||||
```
|
||||
|
||||
* Integer to enum value.
|
||||
|
||||
```cpp
|
||||
int color_integer = 2;
|
||||
auto color = magic_enum::enum_cast<Color>(color_integer);
|
||||
if (color.has_value()) {
|
||||
// color.value() -> Color::RED
|
||||
}
|
||||
```
|
||||
|
||||
## `enum_value`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr E enum_value(size_t index) noexcept;
|
||||
```
|
||||
|
||||
* Returns enum value at specified index.
|
||||
|
||||
* No bounds checking is performed: the behavior is undefined if `index >= number of enum values`.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
int i = 1;
|
||||
Color color = magic_enum::enum_value<Color>(i);
|
||||
// color -> Color::BLUE
|
||||
````
|
||||
|
||||
## `enum_values`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr array<E, N> enum_values() noexcept;
|
||||
```
|
||||
|
||||
* Returns `array<E, N>` with all enum values where `N = number of enum values`, sorted by enum value.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
constexpr auto colors = magic_enum::enum_values<Color>();
|
||||
// colors -> {Color::RED, Color::BLUE, Color::GREEN}
|
||||
// colors[0] -> Color::RED
|
||||
```
|
||||
|
||||
## `enum_count`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr size_t enum_count() noexcept;
|
||||
```
|
||||
|
||||
* Returns number of enum values.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
constexpr auto color_count = magic_enum::enum_count<Color>();
|
||||
// color_count -> 3
|
||||
```
|
||||
|
||||
## `enum_integer`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr underlying_type_t<E> enum_integer(E value) noexcept;
|
||||
```
|
||||
|
||||
* Returns integer value from enum value.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto color_integer = magic_enum::enum_integer(color);
|
||||
// color -> 2
|
||||
```
|
||||
|
||||
## `enum_name`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr string_view enum_name(E value) noexcept;
|
||||
|
||||
template <auto V>
|
||||
constexpr string_view enum_name() noexcept;
|
||||
```
|
||||
|
||||
* Returns name from enum value as `string_view` with null-terminated string.
|
||||
* If enum value does not have name or [out of range](limitations.md), `enum_name(value)` returns empty string.
|
||||
* If enum value does not have name, `enum_name<value>()` occurs the compilation error `"Enum value does not have a name."`.
|
||||
|
||||
* `enum_name<value>()` is much lighter on the compile times and is not restricted to the enum_range [limitation](limitations.md).
|
||||
|
||||
* Examples
|
||||
|
||||
* Enum value to string.
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto color_name = magic_enum::enum_name(color);
|
||||
// color_name -> "RED"
|
||||
```
|
||||
|
||||
* Static storage enum variable to string.
|
||||
|
||||
```cpp
|
||||
constexpr Color color = Color::BLUE;
|
||||
constexpr auto color_name = magic_enum::enum_name<color>();
|
||||
// color_name -> "BLUE"
|
||||
```
|
||||
|
||||
## `enum_names`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr array<string_view, N> enum_names() noexcept;
|
||||
```
|
||||
|
||||
* Returns `array<string_view, N>` with all names where `N = number of enum values`, sorted by enum value.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
constexpr auto color_names = magic_enum::enum_names<Color>();
|
||||
// color_names -> {"RED", "BLUE", "GREEN"}
|
||||
// color_names[0] -> "RED"
|
||||
```
|
||||
|
||||
## `enum_entries`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr array<pair<E, string_view>, N> enum_entries() noexcept;
|
||||
```
|
||||
|
||||
* Returns `array<pair<E, string_view>, N>` with all pairs (value, name) where `N = number of enum values`, sorted by enum value.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
constexpr auto color_entries = magic_enum::enum_entries<Color>();
|
||||
// color_entries -> {{Color::RED, "RED"}, {Color::BLUE, "BLUE"}, {Color::GREEN, "GREEN"}}
|
||||
// color_entries[0].first -> Color::RED
|
||||
// color_entries[0].second -> "RED"
|
||||
```
|
||||
|
||||
## `enum_index`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr optional<size_t> enum_index() noexcept;
|
||||
```
|
||||
|
||||
* Obtains index in enum values from enum value.
|
||||
|
||||
* Returns `optional<size_t>` with index.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
constexpr auto color_index = magic_enum::enum_index(Color::BLUE);
|
||||
// color_index -> color_index.value() -> 1
|
||||
// color_index -> color_index.has_value() -> true
|
||||
```
|
||||
|
||||
## `enum_contains`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr bool enum_contains(E value) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr bool enum_contains(underlying_type_t<E> value) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr bool enum_contains(string_view value) noexcept;
|
||||
|
||||
template <typename E, typename BinaryPredicate>
|
||||
constexpr optional<E> enum_contains(string_view value, BinaryPredicate p) noexcept(is_nothrow_invocable_v<BinaryPredicate>);
|
||||
```
|
||||
|
||||
* Checks whether enum contains enumerator with such value.
|
||||
|
||||
* Returns true is enum contains value, otherwise false.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
magic_enum::enum_contains(Color::GREEN); // -> true
|
||||
magic_enum::enum_contains<Color>(2); // -> true
|
||||
magic_enum::enum_contains<Color>(123); // -> false
|
||||
magic_enum::enum_contains<Color>("GREEN"); // -> true
|
||||
magic_enum::enum_contains<Color>("fda"); // -> false
|
||||
```
|
||||
|
||||
## `enum_type_name`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr string_view enum_type_name() noexcept;
|
||||
```
|
||||
|
||||
* Returns type name of enum as `string_view` null-terminated string.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
Color color = Color::RED;
|
||||
auto type_name = magic_enum::enum_type_name<decltype(color)>();
|
||||
// color_name -> "Color"
|
||||
```
|
||||
|
||||
## `is_unscoped_enum`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_unscoped_enum;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_unscoped_enum_v = is_unscoped_enum<T>::value;
|
||||
```
|
||||
|
||||
* Checks whether type is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration).
|
||||
|
||||
* Provides the member constant value which is equal to true, if T is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration) type.</br>
|
||||
Otherwise, value is equal to false.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
magic_enum::is_unscoped_enum<color>::value -> true
|
||||
magic_enum::is_unscoped_enum<Direction>::value -> false
|
||||
|
||||
// Helper variable template.
|
||||
magic_enum::is_unscoped_enum_v<color> -> true
|
||||
```
|
||||
|
||||
## `is_scoped_enum`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct is_scoped_enum;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_scoped_enum_v = is_scoped_enum<T>::value;
|
||||
```
|
||||
|
||||
* Checks whether type is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations).
|
||||
|
||||
* Provides the member constant value which is equal to true, if T is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations) type.</br>
|
||||
Otherwise, value is equal to false.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
magic_enum::is_scoped_enum<color>::value -> false
|
||||
magic_enum::is_scoped_enum<Direction>::value -> true
|
||||
|
||||
// Helper variable template.
|
||||
magic_enum::is_scoped_enum_v<Direction> -> true
|
||||
```
|
||||
|
||||
## `underlying_type`
|
||||
|
||||
```cpp
|
||||
template <typename T>
|
||||
struct underlying_type;
|
||||
|
||||
template <typename T>
|
||||
using underlying_type_t = typename underlying_type<T>::type;
|
||||
```
|
||||
|
||||
* Improved UB-free "SFINAE-friendly" [underlying_type](https://en.cppreference.com/w/cpp/types/underlying_type).
|
||||
|
||||
* If T is a complete enumeration type, provides a member typedef type that names the underlying type of T.</br>
|
||||
Otherwise, if T is not an enumeration type, there is no member type.</br>
|
||||
Otherwise (T is an incomplete enumeration type), the program is ill-formed.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
magic_enum::underlying_type<color>::type -> int
|
||||
|
||||
// Helper types.
|
||||
magic_enum::underlying_type_t<Direction> -> int
|
||||
```
|
||||
|
||||
## `ostream_operators`
|
||||
|
||||
```cpp
|
||||
template <typename Char, typename Traits, typename E>
|
||||
basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os, E value);
|
||||
|
||||
template <typename Char, typename Traits, typename E>
|
||||
basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os, optional<E> value);
|
||||
|
||||
```
|
||||
|
||||
* Out-of-the-box ostream operators for all enums.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
using namespace magic_enum::ostream_operators; // out-of-the-box ostream operators for enums.
|
||||
Color color = Color::BLUE;
|
||||
std::cout << color << std::endl; // "BLUE"
|
||||
```
|
||||
|
||||
## `bitwise_operators`
|
||||
|
||||
```cpp
|
||||
template <typename E>
|
||||
constexpr E operator~(E rhs) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr E operator|(E lhs, E rhs) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr E operator&(E lhs, E rhs) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr E operator^(E lhs, E rhs) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr E& operator|=(E& lhs, E rhs) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr E& operator&=(E& lhs, E rhs) noexcept;
|
||||
|
||||
template <typename E>
|
||||
constexpr E& operator^=(E& lhs, E rhs) noexcept;
|
||||
```
|
||||
|
||||
* Out-of-the-box bitwise operators for all enums.
|
||||
|
||||
* Examples
|
||||
|
||||
```cpp
|
||||
enum class Flags { A = 1 << 0, B = 1 << 1, C = 1 << 2, D = 1 << 3 };
|
||||
using namespace magic_enum::bitwise_operators; // out-of-the-box bitwise operators for enums.
|
||||
// Support operators: ~, |, &, ^, |=, &=, ^=.
|
||||
Flags flags = Flags::A | Flags::B & ~Flags::C;
|
||||
```
|
||||
22
thirdparty/magic_enum/example/CMakeLists.txt
vendored
Normal file
22
thirdparty/magic_enum/example/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
|
||||
set(OPTIONS -Wall -Wextra -pedantic-errors -Werror)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
set(OPTIONS /W4 /WX)
|
||||
if(HAS_PERMISSIVE_FLAG)
|
||||
set(OPTIONS ${OPTIONS} /permissive-)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(make_example target)
|
||||
add_executable(${target} ${target}.cpp)
|
||||
set_target_properties(${target} PROPERTIES CXX_EXTENSIONS OFF)
|
||||
target_compile_features(${target} PRIVATE cxx_std_17)
|
||||
target_compile_options(${target} PRIVATE ${OPTIONS})
|
||||
target_link_libraries(${target} PRIVATE ${CMAKE_PROJECT_NAME})
|
||||
endfunction()
|
||||
|
||||
make_example(example)
|
||||
make_example(enum_flag_example)
|
||||
make_example(example_custom_name)
|
||||
95
thirdparty/magic_enum/example/enum_flag_example.cpp
vendored
Normal file
95
thirdparty/magic_enum/example/enum_flag_example.cpp
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2019 - 2021 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 <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
enum class AnimalFlags : std::uint64_t { HasClaws = 1 << 10, CanFly = 1 << 20, EatsFish = 1 << 30, Endangered = std::uint64_t{1} << 40 };
|
||||
|
||||
int main() {
|
||||
// Enum-flags variable to string name.
|
||||
AnimalFlags f1 = AnimalFlags::Endangered;
|
||||
auto f1_name = magic_enum::flags::enum_name(f1);
|
||||
std::cout << f1_name << std::endl; // Endangered
|
||||
|
||||
// String enum-flags name sequence.
|
||||
constexpr auto& names = magic_enum::flags::enum_names<AnimalFlags>();
|
||||
std::cout << "AnimalFlags names:";
|
||||
for (const auto& n : names) {
|
||||
std::cout << " " << n;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// AnimalFlags names: HasClaws CanFly EatsFish Endangered
|
||||
|
||||
// String name to enum-flags value.
|
||||
auto f2 = magic_enum::flags::enum_cast<AnimalFlags>("EatsFish|CanFly");
|
||||
if (f2.has_value()) {
|
||||
std::cout << "EatsFish = " << magic_enum::flags::enum_integer(f2.value()) << std::endl; // CanFly|EatsFish = 1074790400
|
||||
}
|
||||
|
||||
// Integer value to enum-flags value.
|
||||
auto f3 = magic_enum::flags::enum_cast<AnimalFlags>(1073742848);
|
||||
if (f3.has_value()) {
|
||||
std::cout << magic_enum::flags::enum_name(f3.value()) << " = " << magic_enum::flags::enum_integer(f3.value()) << std::endl; // HasClaws|EatsFish = 1073742848
|
||||
}
|
||||
|
||||
// Enum-flags value to integer value.
|
||||
auto f4_integer = magic_enum::flags::enum_integer(AnimalFlags::HasClaws);
|
||||
std::cout << "HasClaws = " << f4_integer << std::endl; // HasClaws = 1024
|
||||
|
||||
using namespace magic_enum::flags::ostream_operators; // out-of-the-box ostream operator for enum-flags.
|
||||
// Ostream operator for enum-flags.
|
||||
std::cout << f1 << " " << f2 << " " << f3 << std::endl; // Endangered CanFly|EatsFish HasClaws|EatsFish
|
||||
|
||||
// Number of enum-flags values.
|
||||
std::cout << "AnimalFlags enum size: " << magic_enum::flags::enum_count<AnimalFlags>() << std::endl; // AnimalFlags enum size: 4
|
||||
|
||||
// Indexed access to enum-flags value.
|
||||
std::cout << "AnimalFlags[0] = " << magic_enum::flags::enum_value<AnimalFlags>(0) << std::endl; // AnimalFlags[0] = HasClaws
|
||||
|
||||
// Enum-flags value sequence.
|
||||
constexpr auto& values = magic_enum::flags::enum_values<AnimalFlags>();
|
||||
std::cout << "AnimalFlags values:";
|
||||
for (const auto& f : values) {
|
||||
std::cout << " " << f; // Ostream operator for enum-flags.
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// AnimalFlags sequence: HasClaws CanFly EatsFish Endangered
|
||||
|
||||
using namespace magic_enum::flags::bitwise_operators; // out-of-the-box bitwise operators for all enums.
|
||||
// Support operators: ~, |, &, ^, |=, &=, ^=.
|
||||
AnimalFlags flag = AnimalFlags::HasClaws | AnimalFlags::CanFly;
|
||||
std::cout << flag << std::endl; // HasClaws|CanFly
|
||||
|
||||
// Enum-flags pair (value, string name) sequence.
|
||||
constexpr auto& entries = magic_enum::flags::enum_entries<AnimalFlags>();
|
||||
std::cout << "AnimalFlags entries:";
|
||||
for (const auto& e : entries) {
|
||||
std::cout << " " << e.second << " = " << magic_enum::flags::enum_integer(e.first);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// AnimalFlags entries: AnimalFlags entries: HasClaws = 1024 CanFly = 1048576 EatsFish = 1073741824 Endangered = 1099511627776
|
||||
|
||||
return 0;
|
||||
}
|
||||
113
thirdparty/magic_enum/example/example.cpp
vendored
Normal file
113
thirdparty/magic_enum/example/example.cpp
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2019 - 2021 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 <iostream>
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
enum class Color : int { RED = -10, BLUE = 0, GREEN = 10 };
|
||||
|
||||
template <typename E>
|
||||
auto to_integer(magic_enum::Enum<E> value) {
|
||||
// magic_enum::Enum<E> - C++17 Concept for enum type.
|
||||
return static_cast<magic_enum::underlying_type_t<E>>(value);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Enum variable to string name.
|
||||
Color c1 = Color::RED;
|
||||
auto c1_name = magic_enum::enum_name(c1);
|
||||
std::cout << c1_name << std::endl; // RED
|
||||
|
||||
// String enum name sequence.
|
||||
constexpr auto& names = magic_enum::enum_names<Color>();
|
||||
std::cout << "Color names:";
|
||||
for (const auto& n : names) {
|
||||
std::cout << " " << n;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// Color names: RED BLUE GREEN
|
||||
|
||||
// String name to enum value.
|
||||
auto c2 = magic_enum::enum_cast<Color>("BLUE");
|
||||
if (c2.has_value()) {
|
||||
std::cout << "BLUE = " << to_integer(c2.value()) << std::endl; // BLUE = 0
|
||||
}
|
||||
|
||||
// Integer value to enum value.
|
||||
auto c3 = magic_enum::enum_cast<Color>(10);
|
||||
if (c3.has_value()) {
|
||||
std::cout << "GREEN = " << magic_enum::enum_integer(c3.value()) << std::endl; // GREEN = 10
|
||||
}
|
||||
|
||||
// Enum value to integer value.
|
||||
auto c4_integer = magic_enum::enum_integer(Color::RED);
|
||||
std::cout << "RED = " << c4_integer << std::endl; // RED = -10
|
||||
|
||||
using namespace magic_enum::ostream_operators; // out-of-the-box ostream operator for all enums.
|
||||
// Ostream operator for enum.
|
||||
std::cout << "Color: " << c1 << " " << c2 << " " << c3 << std::endl; // Color: RED BLUE GREEN
|
||||
|
||||
// Number of enum values.
|
||||
std::cout << "Color enum size: " << magic_enum::enum_count<Color>() << std::endl; // Color size: 3
|
||||
|
||||
// Indexed access to enum value.
|
||||
std::cout << "Color[0] = " << magic_enum::enum_value<Color>(0) << std::endl; // Color[0] = RED
|
||||
|
||||
// Enum value sequence.
|
||||
constexpr auto& values = magic_enum::enum_values<Color>();
|
||||
std::cout << "Colors values:";
|
||||
for (const auto& c : values) {
|
||||
std::cout << " " << c; // Ostream operator for enum.
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// Color sequence: RED BLUE GREEN
|
||||
|
||||
enum class Flags { A = 1, B = 2, C = 4, D = 8 };
|
||||
using namespace magic_enum::bitwise_operators; // out-of-the-box bitwise operators for all enums.
|
||||
// Support operators: ~, |, &, ^, |=, &=, ^=.
|
||||
Flags flag = Flags::A | Flags::C;
|
||||
std::cout << flag << std::endl; // 5
|
||||
|
||||
enum color { red, green, blue };
|
||||
|
||||
// Checks whether type is an Unscoped enumeration.
|
||||
static_assert(magic_enum::is_unscoped_enum_v<color>);
|
||||
static_assert(!magic_enum::is_unscoped_enum_v<Color>);
|
||||
static_assert(!magic_enum::is_unscoped_enum_v<Flags>);
|
||||
|
||||
// Checks whether type is an Scoped enumeration.
|
||||
static_assert(!magic_enum::is_scoped_enum_v<color>);
|
||||
static_assert(magic_enum::is_scoped_enum_v<Color>);
|
||||
static_assert(magic_enum::is_scoped_enum_v<Flags>);
|
||||
|
||||
// Enum pair (value enum, string enum name) sequence.
|
||||
constexpr auto& entries = magic_enum::enum_entries<Color>();
|
||||
std::cout << "Colors entries:";
|
||||
for (const auto& e : entries) {
|
||||
std::cout << " " << e.second << " = " << static_cast<int>(e.first);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
// Color entries: RED = -10 BLUE = 0 GREEN = 10
|
||||
|
||||
return 0;
|
||||
}
|
||||
71
thirdparty/magic_enum/example/example_custom_name.cpp
vendored
Normal file
71
thirdparty/magic_enum/example/example_custom_name.cpp
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020 - 2021 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 <iostream>
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
|
||||
enum class Color : int { RED = -10, BLUE = 0, GREEN = 10 };
|
||||
|
||||
// Сustom definitions of names for enum.
|
||||
// Specialization of `enum_name` must be injected in `namespace magic_enum::customize`.
|
||||
template <>
|
||||
constexpr std::string_view magic_enum::customize::enum_name<Color>(Color value) noexcept {
|
||||
switch (value) {
|
||||
case Color::RED:
|
||||
return "the red color";
|
||||
case Color::BLUE:
|
||||
return "The BLUE";
|
||||
case Color::GREEN:
|
||||
return {}; // Empty string for default value.
|
||||
}
|
||||
return {}; // Empty string for unknow value.
|
||||
}
|
||||
|
||||
enum class Numbers : int { One, Two, Three };
|
||||
|
||||
// Сustom definitions of names for enum.
|
||||
// Specialization of `enum_name` must be injected in `namespace magic_enum::customize`.
|
||||
template <>
|
||||
constexpr std::string_view magic_enum::customize::enum_name<Numbers>(Numbers value) noexcept {
|
||||
switch (value) {
|
||||
case Numbers::One:
|
||||
return "the one";
|
||||
default:
|
||||
return {}; // Empty string for default or unknow value.
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << magic_enum::enum_name(Color::RED) << std::endl; // the red color
|
||||
std::cout << magic_enum::enum_name(Color::BLUE) << std::endl; // The BLUE
|
||||
std::cout << magic_enum::enum_name(Color::GREEN) << std::endl; // GREEN
|
||||
|
||||
std::cout << std::boolalpha;
|
||||
std::cout << (magic_enum::enum_cast<Color>("the red color").value() == Color::RED) << std::endl; // true
|
||||
|
||||
std::cout << magic_enum::enum_name(Numbers::One) << std::endl; // the one
|
||||
std::cout << magic_enum::enum_name(Numbers::Two) << std::endl; // Two
|
||||
std::cout << magic_enum::enum_name(Numbers::Three) << std::endl; // Three
|
||||
|
||||
return 0;
|
||||
}
|
||||
1139
thirdparty/magic_enum/include/magic_enum.hpp
vendored
Normal file
1139
thirdparty/magic_enum/include/magic_enum.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
23
thirdparty/magic_enum/test/3rdparty/Catch2/LICENSE
vendored
Normal file
23
thirdparty/magic_enum/test/3rdparty/Catch2/LICENSE
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
17937
thirdparty/magic_enum/test/3rdparty/Catch2/include/catch2/catch.hpp
vendored
Normal file
17937
thirdparty/magic_enum/test/3rdparty/Catch2/include/catch2/catch.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
48
thirdparty/magic_enum/test/CMakeLists.txt
vendored
Normal file
48
thirdparty/magic_enum/test/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
set(SOURCES test.cpp)
|
||||
|
||||
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++latest HAS_CPPLATEST_FLAG)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(OPTIONS -Wall -Wextra -pedantic-errors -Werror)
|
||||
|
||||
check_cxx_compiler_flag(-std=c++20 HAS_CPP20_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)
|
||||
target_link_libraries(${target} PRIVATE ${CMAKE_PROJECT_NAME})
|
||||
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)
|
||||
|
||||
if(HAS_CPP20_FLAG)
|
||||
make_test(test.cpp test-cpp20 c++20)
|
||||
make_test(test_flags.cpp test_flags-cpp20 c++20)
|
||||
endif()
|
||||
|
||||
if(HAS_CPPLATEST_FLAG)
|
||||
make_test(test.cpp test-cpplatest c++latest)
|
||||
make_test(test_flags.cpp test_flags-cpplatest c++latest)
|
||||
endif()
|
||||
739
thirdparty/magic_enum/test/test.cpp
vendored
Normal file
739
thirdparty/magic_enum/test/test.cpp
vendored
Normal file
@@ -0,0 +1,739 @@
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2019 - 2021 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.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
|
||||
enum class Color { RED = -12, GREEN = 7, BLUE = 15 };
|
||||
|
||||
enum class Numbers : int { one = 1, two, three, many = 127 };
|
||||
|
||||
enum Directions { Up = 85, Down = -42, Right = 120, Left = -120 };
|
||||
|
||||
enum number : unsigned long {
|
||||
one = 100,
|
||||
two = 200,
|
||||
three = 300,
|
||||
four = 400,
|
||||
|
||||
#if defined(MAGIC_ENUM_SUPPORTED_ALIASES)
|
||||
_1 = one,
|
||||
_2 = two,
|
||||
_3 = three,
|
||||
_4 = four
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace magic_enum::customize {
|
||||
template <>
|
||||
struct enum_range<number> {
|
||||
static constexpr int min = 100;
|
||||
static constexpr int max = 300;
|
||||
};
|
||||
} // namespace magic_enum
|
||||
|
||||
template <>
|
||||
constexpr std::string_view magic_enum::customize::enum_name<Color>(Color value) noexcept {
|
||||
switch (value) {
|
||||
case Color::RED:
|
||||
return "red";
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
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>("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>("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_FALSE(enum_cast<Numbers>("many").has_value());
|
||||
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 nt = enum_cast<number>("three");
|
||||
REQUIRE(enum_cast<number>("one").value() == number::one);
|
||||
REQUIRE(enum_cast<number>("two").value() == number::two);
|
||||
REQUIRE(nt.value() == number::three);
|
||||
REQUIRE_FALSE(enum_cast<number>("four").has_value());
|
||||
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>(-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());
|
||||
|
||||
constexpr auto no = enum_cast<Numbers>(1);
|
||||
REQUIRE(no.value() == Numbers::one);
|
||||
REQUIRE(enum_cast<Numbers>(2).value() == Numbers::two);
|
||||
REQUIRE(enum_cast<Numbers>(3).value() == Numbers::three);
|
||||
REQUIRE_FALSE(enum_cast<Numbers>(127).has_value());
|
||||
REQUIRE_FALSE(enum_cast<Numbers>(0).has_value());
|
||||
|
||||
constexpr auto dr = enum_cast<Directions>(120);
|
||||
REQUIRE(enum_cast<Directions&>(85).value() == Directions::Up);
|
||||
REQUIRE(enum_cast<const Directions>(-42).value() == Directions::Down);
|
||||
REQUIRE(dr.value() == Directions::Right);
|
||||
REQUIRE(enum_cast<Directions>(-120).value() == Directions::Left);
|
||||
REQUIRE_FALSE(enum_cast<Directions>(0).has_value());
|
||||
|
||||
constexpr auto nt = enum_cast<number>(300);
|
||||
REQUIRE(enum_cast<number>(100).value() == number::one);
|
||||
REQUIRE(enum_cast<number>(200).value() == number::two);
|
||||
REQUIRE(nt.value() == number::three);
|
||||
REQUIRE_FALSE(enum_cast<number>(400).has_value());
|
||||
REQUIRE_FALSE(enum_cast<number>(0).has_value());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("enum_integer") {
|
||||
Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE};
|
||||
constexpr auto cr = enum_integer(Color::RED);
|
||||
Color cg = Color::GREEN;
|
||||
REQUIRE(cr == -12);
|
||||
REQUIRE(enum_integer<Color&>(cg) == 7);
|
||||
REQUIRE(enum_integer(cm[2]) == 15);
|
||||
REQUIRE(enum_integer(static_cast<Color>(0)) == 0);
|
||||
|
||||
constexpr auto no = enum_integer(Numbers::one);
|
||||
REQUIRE(no == 1);
|
||||
REQUIRE(enum_integer(Numbers::two) == 2);
|
||||
REQUIRE(enum_integer(Numbers::three) == 3);
|
||||
REQUIRE(enum_integer(Numbers::many) == 127);
|
||||
REQUIRE(enum_integer(static_cast<Numbers>(0)) == 0);
|
||||
|
||||
constexpr auto dr = enum_integer(Directions::Right);
|
||||
Directions dl = Directions::Left;
|
||||
REQUIRE(enum_integer<Directions&>(dl) == -120);
|
||||
REQUIRE(enum_integer<const Directions>(Directions::Down) == -42);
|
||||
REQUIRE(enum_integer(Directions::Up) == 85);
|
||||
REQUIRE(dr == 120);
|
||||
REQUIRE(enum_integer(static_cast<Directions>(0)) == 0);
|
||||
|
||||
constexpr auto nt = enum_integer(number::three);
|
||||
REQUIRE(enum_integer(number::one) == 100);
|
||||
REQUIRE(enum_integer(number::two) == 200);
|
||||
REQUIRE(nt == 300);
|
||||
REQUIRE(enum_integer(number::four) == 400);
|
||||
REQUIRE(enum_integer(static_cast<number>(0)) == 0);
|
||||
}
|
||||
|
||||
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(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_FALSE(enum_index(Numbers::many).has_value());
|
||||
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 nt = enum_index(number::three);
|
||||
REQUIRE(enum_index(number::one).value() == 0);
|
||||
REQUIRE(enum_index(number::two).value() == 1);
|
||||
REQUIRE(nt.value() == 2);
|
||||
REQUIRE_FALSE(enum_index(number::four).has_value());
|
||||
REQUIRE_FALSE(enum_index(static_cast<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)));
|
||||
|
||||
constexpr auto no = enum_contains(Numbers::one);
|
||||
REQUIRE(no);
|
||||
REQUIRE(enum_contains(Numbers::two));
|
||||
REQUIRE(enum_contains(Numbers::three));
|
||||
REQUIRE_FALSE(enum_contains(Numbers::many));
|
||||
REQUIRE_FALSE(enum_contains(static_cast<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 nt = enum_contains(number::three);
|
||||
REQUIRE(enum_contains(number::one));
|
||||
REQUIRE(enum_contains<number&>(number::two));
|
||||
REQUIRE(nt);
|
||||
REQUIRE_FALSE(enum_contains(number::four));
|
||||
REQUIRE_FALSE(enum_contains(static_cast<number>(0)));
|
||||
}
|
||||
|
||||
SECTION("integer") {
|
||||
REQUIRE(enum_contains<Color>(-12));
|
||||
REQUIRE(enum_contains<Color&>(7));
|
||||
REQUIRE(enum_contains<Color>(15));
|
||||
REQUIRE_FALSE(enum_contains<Color>(42));
|
||||
REQUIRE_FALSE(enum_contains<Color>(-120));
|
||||
REQUIRE_FALSE(enum_contains<Color>(0));
|
||||
|
||||
constexpr auto no = enum_integer(Numbers::one);
|
||||
REQUIRE(enum_contains<Numbers>(no));
|
||||
REQUIRE(enum_contains<Numbers>(enum_integer(Numbers::two)));
|
||||
REQUIRE(enum_contains<Numbers>(enum_integer(Numbers::three)));
|
||||
REQUIRE_FALSE(enum_contains<Numbers>(enum_integer(Numbers::many)));
|
||||
|
||||
constexpr auto dr = enum_integer(Directions::Right);
|
||||
REQUIRE(enum_contains<Directions&>(dr));
|
||||
REQUIRE(enum_contains<const Directions>(Directions::Down));
|
||||
REQUIRE(enum_contains<Directions>(Directions::Up));
|
||||
REQUIRE_FALSE(enum_contains<Directions>(static_cast<Directions>(0)));
|
||||
|
||||
constexpr auto nt = enum_contains<number>(number::three);
|
||||
REQUIRE(enum_contains<number>(number::one));
|
||||
REQUIRE(enum_contains<number>(100));
|
||||
REQUIRE(enum_contains<number>(200));
|
||||
REQUIRE(enum_contains<number>(300));
|
||||
REQUIRE(enum_contains<number>(number::two));
|
||||
REQUIRE(nt);
|
||||
REQUIRE_FALSE(enum_contains<number>(number::four));
|
||||
REQUIRE_FALSE(enum_contains<number>(111));
|
||||
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<Color>("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }));
|
||||
REQUIRE_FALSE(enum_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_FALSE(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 nt = enum_contains<number>("three");
|
||||
REQUIRE(enum_contains<number>("one"));
|
||||
REQUIRE(enum_contains<number>("two"));
|
||||
REQUIRE(nt);
|
||||
REQUIRE_FALSE(enum_contains<number>("four"));
|
||||
REQUIRE_FALSE(enum_contains<number>("None"));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_CASE("enum_values") {
|
||||
REQUIRE(std::is_same_v<decltype(magic_enum::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, 3>{{Numbers::one, Numbers::two, Numbers::three}});
|
||||
|
||||
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, 3>{{number::one, number::two, number::three}});
|
||||
}
|
||||
|
||||
TEST_CASE("enum_count") {
|
||||
constexpr auto s1 = enum_count<Color&>();
|
||||
REQUIRE(s1 == 3);
|
||||
|
||||
constexpr auto s2 = enum_count<Numbers>();
|
||||
REQUIRE(s2 == 3);
|
||||
|
||||
constexpr auto s3 = enum_count<const Directions>();
|
||||
REQUIRE(s3 == 4);
|
||||
|
||||
constexpr auto s4 = enum_count<number>();
|
||||
REQUIRE(s4 == 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 == "red");
|
||||
REQUIRE(enum_name<Color&>(cb) == "BLUE");
|
||||
REQUIRE(enum_name(cm[1]) == "GREEN");
|
||||
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).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(static_cast<Directions>(0)).empty());
|
||||
|
||||
constexpr number nt = number::three;
|
||||
constexpr auto nt_name = enum_name(nt);
|
||||
REQUIRE(enum_name(number::one) == "one");
|
||||
REQUIRE(enum_name(number::two) == "two");
|
||||
REQUIRE(nt_name == "three");
|
||||
REQUIRE(enum_name(number::four).empty());
|
||||
REQUIRE(enum_name(static_cast<number>(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 == "red");
|
||||
REQUIRE(enum_name<Color::BLUE>() == "BLUE");
|
||||
REQUIRE(enum_name<cm[1]>() == "GREEN");
|
||||
|
||||
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");
|
||||
|
||||
constexpr Directions dr = Directions::Right;
|
||||
constexpr auto dr_name = enum_name<dr>();
|
||||
REQUIRE(enum_name<Directions::Up>() == "Up");
|
||||
REQUIRE(enum_name<Directions::Down>() == "Down");
|
||||
REQUIRE(dr_name == "Right");
|
||||
REQUIRE(enum_name<Directions::Left>() == "Left");
|
||||
|
||||
constexpr number nt = number::three;
|
||||
constexpr auto nt_name = enum_name<nt>();
|
||||
REQUIRE(enum_name<number::one>() == "one");
|
||||
REQUIRE(enum_name<number::two>() == "two");
|
||||
REQUIRE(nt_name == "three");
|
||||
REQUIRE(enum_name<number::four>() == "four");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("enum_names") {
|
||||
REQUIRE(std::is_same_v<decltype(magic_enum::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, 3>{{"one", "two", "three"}});
|
||||
|
||||
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, 3>{{"one", "two", "three"}});
|
||||
}
|
||||
|
||||
TEST_CASE("enum_entries") {
|
||||
REQUIRE(std::is_same_v<decltype(magic_enum::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>, 3>{{{Numbers::one, "one"}, {Numbers::two, "two"}, {Numbers::three, "three"}}});
|
||||
|
||||
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>, 3>{{{number::one, "one"}, {number::two, "two"}, {number::three, "three"}}});
|
||||
}
|
||||
|
||||
TEST_CASE("ostream_operators") {
|
||||
auto test_ostream = [](auto e, std::string_view 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(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, "127");
|
||||
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(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, "400");
|
||||
test_ostream(static_cast<number>(0), "0");
|
||||
test_ostream(std::make_optional(static_cast<number>(0)), "0");
|
||||
}
|
||||
|
||||
TEST_CASE("bitwise_operators") {
|
||||
using namespace magic_enum::bitwise_operators;
|
||||
|
||||
SECTION("operator^") {
|
||||
REQUIRE(enum_integer(~Color::RED) == ~enum_integer(Color::RED));
|
||||
REQUIRE(enum_integer(~Numbers::one) == ~enum_integer(Numbers::one));
|
||||
REQUIRE(enum_integer(~Directions::Up) == ~enum_integer(Directions::Up));
|
||||
REQUIRE(enum_integer(~number::one) == ~enum_integer(number::one));
|
||||
}
|
||||
|
||||
SECTION("operator|") {
|
||||
REQUIRE(enum_integer(Color::RED | Color::BLUE) == (enum_integer(Color::RED) | enum_integer(Color::BLUE)));
|
||||
REQUIRE(enum_integer(Numbers::one | Numbers::two) == (enum_integer(Numbers::one) | enum_integer(Numbers::two)));
|
||||
REQUIRE(enum_integer(Directions::Up | Directions::Down) == (enum_integer(Directions::Up) | enum_integer(Directions::Down)));
|
||||
REQUIRE(enum_integer(number::one | number::two) == (enum_integer(number::one) | enum_integer(number::two)));
|
||||
}
|
||||
|
||||
SECTION("operator&") {
|
||||
REQUIRE(enum_integer(Color::RED & Color::BLUE) == (enum_integer(Color::RED) & enum_integer(Color::BLUE)));
|
||||
REQUIRE(enum_integer(Numbers::one & Numbers::two) == (enum_integer(Numbers::one) & enum_integer(Numbers::two)));
|
||||
REQUIRE(enum_integer(Directions::Up & Directions::Down) == (enum_integer(Directions::Up) & enum_integer(Directions::Down)));
|
||||
REQUIRE(enum_integer(number::one & number::two) == (enum_integer(number::one) & enum_integer(number::two)));
|
||||
}
|
||||
|
||||
SECTION("operator^") {
|
||||
REQUIRE(enum_integer(Color::RED ^ Color::BLUE) == (enum_integer(Color::RED) ^ enum_integer(Color::BLUE)));
|
||||
REQUIRE(enum_integer(Numbers::one ^ Numbers::two) == (enum_integer(Numbers::one) ^ enum_integer(Numbers::two)));
|
||||
REQUIRE(enum_integer(Directions::Up ^ Directions::Down) == (enum_integer(Directions::Up) ^ enum_integer(Directions::Down)));
|
||||
REQUIRE(enum_integer(number::one ^ number::two) == (enum_integer(number::one) ^ enum_integer(number::two)));
|
||||
}
|
||||
|
||||
SECTION("operator|=") {
|
||||
Color x1 = Color::RED;
|
||||
x1 |= Color::BLUE;
|
||||
REQUIRE(enum_integer(x1) == (enum_integer(Color::RED) | enum_integer(Color::BLUE)));
|
||||
|
||||
Numbers x2 = Numbers::one;
|
||||
x2 |= Numbers::two;
|
||||
REQUIRE(enum_integer(x2) == (enum_integer(Numbers::one) | enum_integer(Numbers::two)));
|
||||
|
||||
Directions x3 = Directions::Up;
|
||||
x3 |= Directions::Down;
|
||||
REQUIRE(enum_integer(x3) == (enum_integer(Directions::Up) | enum_integer(Directions::Down)));
|
||||
|
||||
number x4 = number::one;
|
||||
x4 |= number::two;
|
||||
REQUIRE(enum_integer(x4) == (enum_integer(number::one) | enum_integer(number::two)));
|
||||
}
|
||||
|
||||
SECTION("operator&=") {
|
||||
Color x1 = Color::RED;
|
||||
x1 &= Color::BLUE;
|
||||
REQUIRE(enum_integer(x1) == (enum_integer(Color::RED) & enum_integer(Color::BLUE)));
|
||||
|
||||
Numbers x2 = Numbers::one;
|
||||
x2 &= Numbers::two;
|
||||
REQUIRE(enum_integer(x2) == (enum_integer(Numbers::one) & enum_integer(Numbers::two)));
|
||||
|
||||
Directions x3 = Directions::Up;
|
||||
x3 &= Directions::Down;
|
||||
REQUIRE(enum_integer(x3) == (enum_integer(Directions::Up) & enum_integer(Directions::Down)));
|
||||
|
||||
number x4 = number::one;
|
||||
x4 &= number::two;
|
||||
REQUIRE(enum_integer(x4) == (enum_integer(number::one) & enum_integer(number::two)));
|
||||
}
|
||||
|
||||
SECTION("operator^=") {
|
||||
Color x1 = Color::RED;
|
||||
x1 ^= Color::BLUE;
|
||||
REQUIRE(enum_integer(x1) == (enum_integer(Color::RED) ^ enum_integer(Color::BLUE)));
|
||||
|
||||
Numbers x2 = Numbers::one;
|
||||
x2 ^= Numbers::two;
|
||||
REQUIRE(enum_integer(x2) == (enum_integer(Numbers::one) ^ enum_integer(Numbers::two)));
|
||||
|
||||
Directions x3 = Directions::Up;
|
||||
x3 ^= Directions::Down;
|
||||
REQUIRE(enum_integer(x3) == (enum_integer(Directions::Up) ^ enum_integer(Directions::Down)));
|
||||
|
||||
number x4 = number::one;
|
||||
x4 ^= number::two;
|
||||
REQUIRE(enum_integer(x4) == (enum_integer(number::one) ^ enum_integer(number::two)));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("type_traits") {
|
||||
REQUIRE_FALSE(is_unscoped_enum_v<Color>);
|
||||
REQUIRE_FALSE(is_unscoped_enum_v<Numbers>);
|
||||
REQUIRE(is_unscoped_enum_v<Directions>);
|
||||
REQUIRE(is_unscoped_enum_v<number>);
|
||||
|
||||
REQUIRE(is_scoped_enum_v<Color>);
|
||||
REQUIRE(is_scoped_enum_v<Numbers>);
|
||||
REQUIRE_FALSE(is_scoped_enum_v<Directions>);
|
||||
REQUIRE_FALSE(is_scoped_enum_v<number>);
|
||||
}
|
||||
|
||||
TEST_CASE("enum_type_name") {
|
||||
REQUIRE(enum_type_name<Color&>() == "Color");
|
||||
REQUIRE(enum_type_name<const Numbers>() == "Numbers");
|
||||
REQUIRE(enum_type_name<const Directions&>() == "Directions");
|
||||
REQUIRE(enum_type_name<number>() == "number");
|
||||
}
|
||||
|
||||
#if defined(MAGIC_ENUM_SUPPORTED_ALIASES)
|
||||
TEST_CASE("aliases") {
|
||||
REQUIRE(enum_count<number>() == 3);
|
||||
|
||||
REQUIRE(enum_name(number::one) == enum_name(number::_1));
|
||||
REQUIRE(enum_name(number::two) == enum_name(number::_2));
|
||||
REQUIRE(enum_name(number::three) == enum_name(number::_3));
|
||||
REQUIRE(enum_name(number::four) == enum_name(number::_4));
|
||||
|
||||
REQUIRE(enum_integer(number::one) == enum_integer(number::_1));
|
||||
REQUIRE(enum_integer(number::two) == enum_integer(number::_2));
|
||||
REQUIRE(enum_integer(number::three) == enum_integer(number::_3));
|
||||
REQUIRE(enum_integer(number::four) == enum_integer(number::_4));
|
||||
|
||||
REQUIRE_FALSE(enum_cast<number>("_1").has_value());
|
||||
REQUIRE_FALSE(enum_cast<number>("_2").has_value());
|
||||
REQUIRE_FALSE(enum_cast<number>("_3").has_value());
|
||||
REQUIRE_FALSE(enum_cast<number>("_4").has_value());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("extrema") {
|
||||
enum class BadColor : std::uint64_t {
|
||||
RED,
|
||||
GREEN,
|
||||
YELLOW,
|
||||
// The value NONE is ignored (out of range).
|
||||
// However, it affects the value of min_v. When reflected_min_v was incorrect,
|
||||
// the presence of NONE caused miv_v to be equal to -1, which was then cast to unsigned,
|
||||
// leading to a value of 18446744073709551615 (numeric_limit_max of uint64_t).
|
||||
NONE = std::numeric_limits<std::uint64_t>::max()
|
||||
};
|
||||
|
||||
REQUIRE(magic_enum::enum_name<BadColor>(BadColor::NONE).empty());
|
||||
REQUIRE_FALSE(magic_enum::enum_cast<BadColor>(std::numeric_limits<std::uint64_t>::max()).has_value());
|
||||
REQUIRE_FALSE(magic_enum::enum_contains<BadColor>(std::numeric_limits<std::uint64_t>::max()));
|
||||
REQUIRE_FALSE(magic_enum::enum_contains<BadColor>(BadColor::NONE));
|
||||
|
||||
SECTION("min") {
|
||||
REQUIRE(magic_enum::customize::enum_range<BadColor>::min == MAGIC_ENUM_RANGE_MIN);
|
||||
REQUIRE(magic_enum::detail::reflected_min_v<BadColor> == 0);
|
||||
REQUIRE(magic_enum::detail::min_v<BadColor> == 0);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<Color>::min == MAGIC_ENUM_RANGE_MIN);
|
||||
REQUIRE(magic_enum::detail::reflected_min_v<Color> == MAGIC_ENUM_RANGE_MIN);
|
||||
REQUIRE(magic_enum::detail::min_v<Color> == -12);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<Numbers>::min == MAGIC_ENUM_RANGE_MIN);
|
||||
REQUIRE(magic_enum::detail::reflected_min_v<Numbers> == MAGIC_ENUM_RANGE_MIN);
|
||||
REQUIRE(magic_enum::detail::min_v<Numbers> == 1);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<Directions>::min == MAGIC_ENUM_RANGE_MIN);
|
||||
REQUIRE(magic_enum::detail::reflected_min_v<Directions> == MAGIC_ENUM_RANGE_MIN);
|
||||
REQUIRE(magic_enum::detail::min_v<Directions> == -120);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<number>::min == 100);
|
||||
REQUIRE(magic_enum::detail::reflected_min_v<number> == 100);
|
||||
REQUIRE(magic_enum::detail::min_v<number> == 100);
|
||||
}
|
||||
|
||||
SECTION("max") {
|
||||
REQUIRE(magic_enum::customize::enum_range<BadColor>::max == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::reflected_max_v<BadColor> == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::max_v<BadColor> == 2);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<Color>::max == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::reflected_max_v<Color> == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::max_v<Color> == 15);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<Numbers>::max == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::reflected_max_v<Numbers> == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::max_v<Numbers> == 3);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<Directions>::max == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::reflected_max_v<Directions> == MAGIC_ENUM_RANGE_MAX);
|
||||
REQUIRE(magic_enum::detail::max_v<Directions> == 120);
|
||||
|
||||
REQUIRE(magic_enum::customize::enum_range<number>::max == 300);
|
||||
REQUIRE(magic_enum::detail::reflected_max_v<number> == 300);
|
||||
REQUIRE(magic_enum::detail::max_v<number> == 300);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("cmp_less") {
|
||||
using magic_enum::detail::cmp_less;
|
||||
|
||||
constexpr std::uint64_t uint64_t_min = std::numeric_limits<std::uint64_t>::min();
|
||||
constexpr std::uint32_t uint32_t_min = std::numeric_limits<std::uint32_t>::min();
|
||||
constexpr std::uint32_t uint32_t_max = std::numeric_limits<std::uint32_t>::max();
|
||||
constexpr std::uint64_t uint64_t_max = std::numeric_limits<std::uint64_t>::max();
|
||||
|
||||
constexpr std::int64_t int64_t_min = std::numeric_limits<std::int64_t>::min();
|
||||
constexpr std::int32_t int32_t_min = std::numeric_limits<std::int32_t>::min();
|
||||
constexpr std::int32_t int32_t_max = std::numeric_limits<std::int32_t>::max();
|
||||
constexpr std::int64_t int64_t_max = std::numeric_limits<std::int64_t>::max();
|
||||
|
||||
// Also testing with offset to avoid corner cases.
|
||||
// Two variables to avoid hidden casts:
|
||||
constexpr std::int64_t offset_int64_t = 17;
|
||||
constexpr std::int32_t offset_int32_t = 17;
|
||||
|
||||
SECTION("same signedness") {
|
||||
REQUIRE(cmp_less(-5, -3));
|
||||
REQUIRE(cmp_less(27U, 49U));
|
||||
}
|
||||
|
||||
SECTION("same signedness, different width") {
|
||||
REQUIRE(cmp_less(uint32_t_max, uint64_t_max));
|
||||
REQUIRE_FALSE(cmp_less(uint64_t_max, uint32_t_max));
|
||||
REQUIRE(cmp_less(int64_t_min, int32_t_min));
|
||||
REQUIRE_FALSE(cmp_less(int32_t_min, int64_t_min));
|
||||
REQUIRE(cmp_less(int64_t_min + offset_int64_t, int32_t_min + offset_int32_t));
|
||||
REQUIRE_FALSE(cmp_less(int32_t_min + offset_int32_t, int64_t_min + offset_int64_t));
|
||||
}
|
||||
|
||||
SECTION("left signed, right unsigned") {
|
||||
REQUIRE(cmp_less(-5, 3U));
|
||||
REQUIRE(cmp_less(3, 5U));
|
||||
}
|
||||
|
||||
SECTION("left signed, right unsigned, different width") {
|
||||
REQUIRE(cmp_less(int32_t_max, uint64_t_max));
|
||||
REQUIRE_FALSE(cmp_less(int64_t_max, uint32_t_max));
|
||||
REQUIRE(cmp_less(int32_t_min, uint64_t_min));
|
||||
REQUIRE(cmp_less(int64_t_min, uint32_t_min));
|
||||
REQUIRE(cmp_less(int32_t_max - offset_int32_t, uint64_t_max));
|
||||
REQUIRE_FALSE(cmp_less(int64_t_max - offset_int64_t, uint32_t_max));
|
||||
REQUIRE(cmp_less(int32_t_min + offset_int32_t, uint64_t_min));
|
||||
REQUIRE(cmp_less(int64_t_min + offset_int64_t, uint32_t_min));
|
||||
}
|
||||
|
||||
SECTION("left unsigned, right signed") {
|
||||
REQUIRE_FALSE(cmp_less(3U, -5));
|
||||
REQUIRE(cmp_less(3U, 5));
|
||||
}
|
||||
|
||||
SECTION("left unsigned, right signed, different width") {
|
||||
REQUIRE(cmp_less(uint32_t_max, int64_t_max));
|
||||
REQUIRE_FALSE(cmp_less(uint64_t_max, int32_t_max));
|
||||
REQUIRE_FALSE(cmp_less(uint32_t_min, int64_t_min));
|
||||
REQUIRE_FALSE(cmp_less(uint64_t_min, int32_t_min));
|
||||
REQUIRE(cmp_less(uint32_t_max, int64_t_max - offset_int32_t));
|
||||
REQUIRE_FALSE(cmp_less(uint64_t_max, int32_t_max - offset_int64_t));
|
||||
REQUIRE_FALSE(cmp_less(uint32_t_min, int64_t_min + offset_int32_t));
|
||||
REQUIRE_FALSE(cmp_less(uint64_t_min, int32_t_min + offset_int64_t));
|
||||
}
|
||||
}
|
||||
549
thirdparty/magic_enum/test/test_flags.cpp
vendored
Normal file
549
thirdparty/magic_enum/test/test_flags.cpp
vendored
Normal file
@@ -0,0 +1,549 @@
|
||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2019 - 2021 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.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
|
||||
enum class Color { RED = 1, GREEN = 2, BLUE = 4 };
|
||||
|
||||
enum class Numbers : int {
|
||||
one = 1 << 1,
|
||||
two = 1 << 2,
|
||||
three = 1 << 3,
|
||||
many = 1 << 30,
|
||||
};
|
||||
|
||||
enum Directions : std::uint64_t {
|
||||
Left = std::uint64_t{1} << 10,
|
||||
Down = std::uint64_t{1} << 20,
|
||||
Up = std::uint64_t{1} << 31,
|
||||
Right = std::uint64_t{1} << 63,
|
||||
};
|
||||
|
||||
enum number : unsigned long {
|
||||
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
|
||||
};
|
||||
|
||||
namespace magic_enum::customize {
|
||||
template <>
|
||||
struct enum_range<number> {
|
||||
static constexpr int min = 100;
|
||||
static constexpr int max = 300;
|
||||
};
|
||||
} // namespace magic_enum
|
||||
|
||||
using namespace magic_enum::flags;
|
||||
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(enum_cast<Color&>("blue|RED", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }).value() == (Color::BLUE | Color::RED));
|
||||
REQUIRE(enum_cast<Color&>("GREEN|RED").value() == (Color::GREEN | Color::RED));
|
||||
REQUIRE(enum_cast<Color&>("GREEN|RED|RED").value() == (Color::GREEN | Color::RED));
|
||||
REQUIRE_FALSE(enum_cast<Color&>("GREEN|RED|None").has_value());
|
||||
REQUIRE_FALSE(enum_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_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(enum_cast<Color>(1 | 2).value() == (Color::GREEN | Color::RED));
|
||||
REQUIRE(enum_cast<Color>(1 | 2 | 1).value() == (Color::GREEN | Color::RED));
|
||||
REQUIRE_FALSE(enum_cast<Color>(1 | 2 | 8).has_value());
|
||||
REQUIRE_FALSE(enum_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_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(enum_contains<Color>(Color::RED | Color::GREEN));
|
||||
REQUIRE(enum_contains<Color>(Color::RED | Color::GREEN | Color::GREEN));
|
||||
REQUIRE_FALSE(enum_contains<Color>(Color::RED | Color{8}));
|
||||
REQUIRE_FALSE(enum_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(nto);
|
||||
REQUIRE_FALSE(enum_contains(static_cast<number>(0)));
|
||||
}
|
||||
|
||||
SECTION("integer") {
|
||||
REQUIRE(enum_contains<Color>(1));
|
||||
REQUIRE(enum_contains<Color&>(2));
|
||||
REQUIRE(enum_contains<Color>(4));
|
||||
REQUIRE(enum_contains<Color>(1 | 2));
|
||||
REQUIRE(enum_contains<Color>(1 | 2 | 1));
|
||||
REQUIRE_FALSE(enum_contains<Color>(1 | 2 | 8));
|
||||
REQUIRE_FALSE(enum_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(enum_contains<number>(8 | 2 | 16));
|
||||
REQUIRE(enum_contains<number>(8 | 16 | 16));
|
||||
REQUIRE(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<Color>("blue", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }));
|
||||
REQUIRE(enum_contains<Color&>("blue|RED", [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }));
|
||||
REQUIRE(enum_contains<Color&>("GREEN|RED"));
|
||||
REQUIRE(enum_contains<Color&>("GREEN|RED|RED"));
|
||||
REQUIRE_FALSE(enum_contains<Color>("GREEN|RED|None"));
|
||||
REQUIRE_FALSE(enum_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(nto);
|
||||
REQUIRE_FALSE(enum_contains<number>("None"));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_CASE("enum_values") {
|
||||
REQUIRE(std::is_same_v<decltype(magic_enum::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;
|
||||
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) == "RED|GREEN");
|
||||
REQUIRE(enum_name(Color::RED | Color{8}).empty());
|
||||
REQUIRE(enum_name(static_cast<Color>(0)).empty());
|
||||
|
||||
constexpr Numbers no = Numbers::one;
|
||||
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) == "two|many");
|
||||
REQUIRE(enum_name(static_cast<Numbers>(0)).empty());
|
||||
|
||||
constexpr Directions dr = Directions::Right;
|
||||
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) == "Left|Down|Up|Right");
|
||||
REQUIRE(enum_name(static_cast<Directions>(0)).empty());
|
||||
|
||||
constexpr number nto = number::three | number::one;
|
||||
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 == "one|three");
|
||||
REQUIRE(enum_name(static_cast<number>(0)).empty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("enum_names") {
|
||||
REQUIRE(std::is_same_v<decltype(magic_enum::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(magic_enum::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_view name) {
|
||||
using namespace magic_enum::flags::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("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)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user