1
0
Fork 0
mirror of https://github.com/Neargye/magic_enum.git synced 2026-01-09 23:34:23 +00:00
This commit is contained in:
terik23 2019-03-31 02:24:36 +05:00
commit ac6444fae5
13 changed files with 15671 additions and 0 deletions

33
.appveyor.yml Normal file
View file

@ -0,0 +1,33 @@
version: "{branch} #{build}"
shallow_clone: true
image:
- Visual Studio 2017
platform:
- Win32
- x64
configuration:
- Debug
- Release
build:
parallel: true
environment:
matrix:
- GENERATOR: "Visual Studio 15 2017"
before_build:
- if exist build RMDIR /S /Q build
- if not exist build mkdir build
- cd build
- cmake -G "%GENERATOR%" -A %PLATFORM% ..
build_script:
- cmake --build . --config %CONFIGURATION%
test_script:
- ctest --output-on-failure -C %CONFIGURATION%

48
.gitignore vendored Normal file
View file

@ -0,0 +1,48 @@
build/
### 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

126
.travis.yml Normal file
View file

@ -0,0 +1,126 @@
os: linux # Use linux unless specified otherwise.
dist: xenial
sudo: required
language: cpp
git:
depth: 1
matrix:
include:
- os: linux
compiler: g++
env:
- CXX_COMPILER=g++-9 CC_COMPILER=gcc-9
- os: linux
compiler: clang++
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-5.0
packages:
- clang-5.0
env:
- CXX_COMPILER=clang++-5.0 CC_COMPILER=clang-5.0
- os: linux
compiler: clang++
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-6.0
packages:
- clang-6.0
env:
- CXX_COMPILER=clang++-6.0 CC_COMPILER=clang-6.0
- os: linux
compiler: clang++
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-7
packages:
- clang-7
env:
- CXX_COMPILER=clang++-7 CC_COMPILER=clang-7
- os: linux
compiler: clang++
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
packages:
- clang-8
env:
- CXX_COMPILER=clang++-8 CC_COMPILER=clang-8
- os: osx
compiler: clang++
osx_image: xcode10.2
env:
- CXX_COMPILER=clang++ CC_COMPILER=clang
install:
- export CC=${CC_COMPILER}
- export CXX=${CXX_COMPILER}
- JOBS=2 # Travis machines have 2 cores.
- |
# If linux and clang install the right version of libc++.
if [[ "${TRAVIS_OS_NAME}" == "linux" && "${CXX%%+*}" == "clang" && -n "$(ls -A ${LLVM_INSTALL})" ]]; then
LLVM_INSTALL=${DEPS_DIR}/llvm/install
if [[ "${CXX}" == "clang++-3.5" ]]; then LLVM_VERSION="3.5.2";
elif [[ "${CXX}" == "clang++-3.6" ]]; then LLVM_VERSION="3.6.2";
elif [[ "${CXX}" == "clang++-3.7" ]]; then LLVM_VERSION="3.7.1";
elif [[ "${CXX}" == "clang++-3.8" ]]; then LLVM_VERSION="3.8.1";
elif [[ "${CXX}" == "clang++-3.9" ]]; then LLVM_VERSION="3.9.1";
elif [[ "${CXX}" == "clang++-4.0" ]]; then LLVM_VERSION="4.0.1";
elif [[ "${CXX}" == "clang++-5.0" ]]; then LLVM_VERSION="5.0.2";
elif [[ "${CXX}" == "clang++-6.0" ]]; then LLVM_VERSION="6.0.1";
elif [[ "${CXX}" == "clang++-7" ]]; then LLVM_VERSION="7.0.1";
elif [[ "${CXX}" == "clang++-8" ]]; then LLVM_VERSION="8.0.0";
fi
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz"
LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz"
LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz"
mkdir -p llvm llvm/build llvm/projects/libcxx llvm/projects/libcxxabi
travis_retry wget -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C llvm
travis_retry wget -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxx
travis_retry wget -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxxabi
(cd llvm/build && cmake .. -DCMAKE_INSTALL_PREFIX=${LLVM_INSTALL})
(cd llvm/build/projects/libcxx && sudo make install -j${JOBS})
(cd llvm/build/projects/libcxxabi && sudo make install -j${JOBS})
export CXXFLAGS="-isystem ${LLVM_INSTALL}/include/c++/v1"
export LDFLAGS="-L ${LLVM_INSTALL}/lib -l c++ -l c++abi"
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_INSTALL}/lib"
fi
- |
# If linux and gcc-9 install gcc-9.
if [[ "${CXX}" == "g++-9" ]]; then
wget http://kayari.org/gcc-latest/gcc-latest.deb
sudo dpkg -i gcc-latest.deb
sudo ln -s /opt/gcc-latest/bin/gcc /usr/bin/gcc-9
sudo ln -s /opt/gcc-latest/bin/g++ /usr/bin/g++-9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 --slave /usr/bin/g++ g++ /usr/bin/g++-9
sudo ldconfig /opt/gcc-latest/lib64
fi
before_script:
- rm -rf build
- mkdir -p build
- cd build
- cmake -G "Unix Makefiles" ..
script:
- cmake --build . -- -j${JOBS}
- ctest --output-on-failure -j${JOBS}
notifications:
email: false

15
CMakeLists.txt Normal file
View file

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.6)
project(magic_enum VERSION "0.1.0" LANGUAGES CXX)
option(MAGIC_ENUM_OPT_BUILD_EXAMPLES "Build magic_enum examples" ON)
option(MAGIC_ENUM_OPT_BUILD_TESTS "Build and perform magic_enum tests" ON)
if(MAGIC_ENUM_OPT_BUILD_EXAMPLES)
add_subdirectory(example)
endif()
if(MAGIC_ENUM_OPT_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif()

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 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.

72
README.md Normal file
View file

@ -0,0 +1,72 @@
# Magic Enum C++
```text
__ __ _ ______ _____
| \/ | (_) | ____| / ____|_ _
| \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
| |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
| | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
|_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
__/ |
|___/
```
Branch | Linux/OSX | Windows | License | Codacy
-------|-----------|---------|---------|-------
master |-----------|---------|---------|-------
## What is Magic Enum?
Header-only C++17 library provides Enum-to-String and String-to-Enum functions.
* `magic_enum::enum_to_string` obtain string enum name from enum variable.
* `magic_enum::enum_from_string` obtain enum variable from enum string name.
## Features
* C++17
* Header-only
* Dependency-free
* Compile-time
* Enum to string
* String to enum
## [Examples](example/example.cpp)
* Enum to string
```cpp
auto color = Color::RED;
// Enum variable to string enum name
auto color_name = magic_enum::enum_to_string(c);
if (color_name.has_value()) {
// color_name.value() -> "RED"
}
constexpr auto cx_color = Color::BLUE;
// Static storage enum variable to string enum name
auto cx_color_name = magic_enum::enum_to_string<cx_color>();
if (color_name.has_value()) {
// cx_color_name.value() -> "BLUE"
}
```
* String to enum
```cpp
// String enum name to enum variable
auto color = magic_enum::enum_from_string<Color>("GREEN");
if (color.has_value()) {
// color.value() -> Color::GREEN
}
```
## Integration
You have to add required file [magic_enum.hpp](include/magic_enum.hpp).
## Compiler compatibility
* Clang/LLVM >= 5
* Visual C++ >= 15.3 / Visual Studio >= 2017
* Xcode >= 10.2
* GCC >= 9
## Licensed under the [MIT License](LICENSE)

23
example/CMakeLists.txt Normal file
View file

@ -0,0 +1,23 @@
include(CheckCXXCompilerFlag)
include_directories(${CMAKE_SOURCE_DIR}/include)
set(OPTIONS "")
if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
set(CMAKE_VERBOSE_MAKEFILE ON)
set(OPTIONS -Wall -Wextra -pedantic-errors)
set(OPTIONS ${OPTIONS} -std=c++17)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(OPTIONS /W4)
check_cxx_compiler_flag(/permissive HAS_PERMISSIVE_FLAG)
if(HAS_PERMISSIVE_FLAG)
set(OPTIONS ${OPTIONS} /permissive-)
endif()
set(OPTIONS ${OPTIONS} /std:c++17)
endif()
add_executable(example
example.cpp
${CMAKE_SOURCE_DIR}/include/magic_enum.hpp)
target_compile_options(example PRIVATE ${OPTIONS})

51
example/example.cpp Normal file
View file

@ -0,0 +1,51 @@
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 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 <magic_enum.hpp>
#include <iostream>
enum Color { RED = -10, BLUE = 0, GREEN = 10 };
int main() {
// Enum variable to string enum name.
auto c1 = Color::RED;
auto c1_name = magic_enum::enum_to_string(c1);
if (c1_name.has_value()) {
std::cout << c1_name.value() << std::endl; // RED
}
// String enum name to enum variable.
auto c2 = magic_enum::enum_from_string<Color>("GREEN");
if (c2.has_value() && c2.value() == Color::GREEN) {
std::cout << "GREEN = " << c2.value() << std::endl; // GREEN = 10
}
// Static storage enum variable to string enum name.
constexpr auto cx = Color::BLUE;
auto cx_name = magic_enum::enum_to_string<cx>();
if (cx_name.has_value()) {
std::cout << cx_name.value() << std::endl; // BLUE
}
return 0;
}

158
include/magic_enum.hpp Normal file
View file

@ -0,0 +1,158 @@
// __ __ _ ______ _____
// | \/ | (_) | ____| / ____|_ _
// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_
// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _|
// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_|
// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____|
// __/ | https://github.com/Neargye/magic_enum
// |___/ vesion 0.1.0
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 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.
#pragma once
#include <cstddef>
#include <type_traits>
#include <limits>
#include <string_view>
#include <optional>
#if !defined(MAGIC_ENUM_MAX_SEARCH_DEPTH)
# define MAGIC_ENUM_MAX_SEARCH_DEPTH 128
#endif
namespace magic_enum {
static_assert(MAGIC_ENUM_MAX_SEARCH_DEPTH > 0,
"MAGIC_ENUM_MAX_SEARCH_DEPTH must be positive and greater than zero.");
static_assert(MAGIC_ENUM_MAX_SEARCH_DEPTH % 8 == 0,
"MAGIC_ENUM_MAX_SEARCH_DEPTH must be a multiple of 8.");
static_assert(MAGIC_ENUM_MAX_SEARCH_DEPTH < std::numeric_limits<int>::max(),
"MAGIC_ENUM_MAX_SEARCH_DEPTH must be less INT_MAX.");
namespace detail {
[[nodiscard]] constexpr bool is_name_char(char c) noexcept {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
template <auto V>
[[nodiscard]] constexpr std::optional<std::string_view> enum_to_string_impl() noexcept {
static_assert(std::is_enum_v<decltype(V)>);
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 9)
std::string_view name{__PRETTY_FUNCTION__};
constexpr auto suffix = sizeof("]") - 1;
#elif defined(_MSC_VER)
std::string_view name{__FUNCSIG__};
constexpr auto suffix = sizeof(">(void) noexcept") - 1;
#else
return std::nullopt; // Unsupported compiler.
#endif
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 9) || defined(_MSC_VER)
name.remove_suffix(suffix);
for (std::size_t i = name.size(); i > 0; --i) {
if (!is_name_char(name[i - 1])) {
name.remove_prefix(i);
break;
}
}
if (name.front() >= '0' && name.front() <= '9') {
return std::nullopt; // Enum variable does not have name.
} else {
return name;
}
#endif
}
template <typename E, int V>
struct enum_to_string_impl_t final {
[[nodiscard]] constexpr std::optional<std::string_view> operator()(int value) const noexcept {
static_assert(std::is_enum_v<E>);
if constexpr (V > std::numeric_limits<std::underlying_type_t<E>>::max()) {
return std::nullopt; // Enum variable out of range.
}
switch (value - V) {
case 0:
return enum_to_string_impl<static_cast<E>(V)>();
case 1:
return enum_to_string_impl<static_cast<E>(V + 1)>();
case 2:
return enum_to_string_impl<static_cast<E>(V + 2)>();
case 3:
return enum_to_string_impl<static_cast<E>(V + 3)>();
case 4:
return enum_to_string_impl<static_cast<E>(V + 4)>();
case 5:
return enum_to_string_impl<static_cast<E>(V + 5)>();
case 6:
return enum_to_string_impl<static_cast<E>(V + 6)>();
case 7:
return enum_to_string_impl<static_cast<E>(V + 7)>();
default:
return enum_to_string_impl_t<E, V + 8>{}(value);
}
}
};
template <typename E>
struct enum_to_string_impl_t<E, MAGIC_ENUM_MAX_SEARCH_DEPTH> final {
[[nodiscard]] constexpr std::optional<std::string_view> operator()(int) const noexcept {
static_assert(std::is_enum_v<E>);
return std::nullopt; // Enum variable out of range MAGIC_ENUM_MAX_SEARCH_DEPTH.
}
};
} // namespace detail
// enum_to_string(value) used to obtain string enum name from enum variable.
template <typename T, typename = std::enable_if_t<std::is_enum_v<std::decay_t<T>>>>
[[nodiscard]] constexpr std::optional<std::string_view> enum_to_string(T value) noexcept {
constexpr bool s = std::is_signed_v<std::underlying_type_t<std::decay_t<T>>>;
constexpr int min = s ? -MAGIC_ENUM_MAX_SEARCH_DEPTH : 0;
return detail::enum_to_string_impl_t<std::decay_t<T>, min>{}(static_cast<int>(value));
}
// enum_to_string<value>() used to obtain string enum name from static storage enum variable
template <auto V, typename = std::enable_if_t<std::is_enum_v<std::decay_t<decltype(V)>>>>
[[nodiscard]] constexpr std::optional<std::string_view> enum_to_string() noexcept {
return detail::enum_to_string_impl<V>();
}
// enum_from_string(name) used to obtain enum variable from enum string name.
template <typename E, typename = std::enable_if_t<std::is_enum_v<E>>>
[[nodiscard]] constexpr std::optional<E> enum_from_string(std::string_view name) noexcept {
constexpr bool s = std::is_signed_v<std::underlying_type_t<E>>;
constexpr int min = s ? -MAGIC_ENUM_MAX_SEARCH_DEPTH : 0;
for (int i = min; i < MAGIC_ENUM_MAX_SEARCH_DEPTH; ++i) {
if (detail::enum_to_string_impl_t<E, min>{}(i) == name) {
return static_cast<E>(i);
}
}
return std::nullopt; // Argument name has not been enum variable name.
}
} // namespace magic_enum

23
test/3rdparty/Catch2/LICENSE vendored Normal file
View file

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

14934
test/3rdparty/Catch2/catch.hpp vendored Normal file

File diff suppressed because it is too large Load diff

53
test/CMakeLists.txt Normal file
View file

@ -0,0 +1,53 @@
include(CheckCXXCompilerFlag)
include_directories(3rdparty/Catch2)
include_directories(${CMAKE_SOURCE_DIR}/include)
set(SOURCES test.cpp)
set(OPTIONS "")
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(OPTIONS /W4)
check_cxx_compiler_flag(/permissive HAS_PERMISSIVE_FLAG)
if(HAS_PERMISSIVE_FLAG)
set(OPTIONS ${OPTIONS} /permissive-)
endif()
set(OPTIONS ${OPTIONS} /wd4702) # Disable warning C4702: unreachable code
set(HAS_CPP11_FLAG TRUE)
check_cxx_compiler_flag(/std:c++14 HAS_CPP14_FLAG)
check_cxx_compiler_flag(/std:c++17 HAS_CPP17_FLAG)
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)
check_cxx_compiler_flag(-std=c++11 HAS_CPP11_FLAG)
check_cxx_compiler_flag(-std=c++14 HAS_CPP14_FLAG)
check_cxx_compiler_flag(-std=c++17 HAS_CPP17_FLAG)
check_cxx_compiler_flag(-std=c++20 HAS_CPP20_FLAG)
endif()
function(make_target target std)
add_executable(${target} ${SOURCES})
target_compile_options(${target} PRIVATE ${OPTIONS})
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()
endfunction()
if(HAS_CPP17_FLAG)
make_target(${CMAKE_PROJECT_NAME}-cpp17.t c++17)
add_test(NAME ${CMAKE_PROJECT_NAME}-cpp17.t COMMAND ${CMAKE_PROJECT_NAME}-cpp17.t)
endif()
if(HAS_CPPLATEST_FLAG)
make_target(${CMAKE_PROJECT_NAME}-cpplatest.t c++latest)
add_test(NAME ${CMAKE_PROJECT_NAME}-cpplatest.t COMMAND ${CMAKE_PROJECT_NAME}-cpplatest.t)
endif()

114
test/test.cpp Normal file
View file

@ -0,0 +1,114 @@
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2019 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 <catch.hpp>
#define MAGIC_ENUM_MAX_SEARCH_DEPTH 120
#include <magic_enum.hpp>
enum class Color { RED = -12, GREEN = 7, BLUE = 15 };
enum class Numbers : char { one = 10, two = 20, three = 30 };
enum Directions { Up = 85, Down = -42, Right = 119, Left = -119 };
enum number : int { one = 10, two = 20, three = 30 };
TEST_CASE("magic_enum::enum_to_string(value)") {
Color cr = Color::RED;
Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE};
REQUIRE(magic_enum::enum_to_string(cr).value() == "RED");
REQUIRE(magic_enum::enum_to_string(Color::BLUE).value() == "BLUE");
REQUIRE(magic_enum::enum_to_string(cm[1]).value() == "GREEN");
REQUIRE(!magic_enum::enum_to_string(static_cast<Color>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value());
Numbers no = Numbers::one;
REQUIRE(magic_enum::enum_to_string(no).value() == "one");
REQUIRE(magic_enum::enum_to_string(Numbers::two).value() == "two");
REQUIRE(magic_enum::enum_to_string(Numbers::three).value() == "three");
REQUIRE(!magic_enum::enum_to_string(static_cast<Numbers>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value());
Directions dr = Directions::Right;
REQUIRE(magic_enum::enum_to_string(Directions::Up).value() == "Up");
REQUIRE(magic_enum::enum_to_string(Directions::Down).value() == "Down");
REQUIRE(magic_enum::enum_to_string(dr).value() == "Right");
REQUIRE(magic_enum::enum_to_string(Directions::Left).value() == "Left");
REQUIRE(!magic_enum::enum_to_string(static_cast<Directions>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value());
number nt = number::three;
REQUIRE(magic_enum::enum_to_string(number::one).value() == "one");
REQUIRE(magic_enum::enum_to_string(number::two).value() == "two");
REQUIRE(magic_enum::enum_to_string(nt).value() == "three");
REQUIRE(!magic_enum::enum_to_string(static_cast<number>(MAGIC_ENUM_MAX_SEARCH_DEPTH)).has_value());
}
TEST_CASE("magic_enum::enum_to_string<value>()") {
constexpr Color cr = Color::RED;
constexpr Color cm[3] = {Color::RED, Color::GREEN, Color::BLUE};
REQUIRE(magic_enum::enum_to_string<cr>().value() == "RED");
REQUIRE(magic_enum::enum_to_string<Color::BLUE>().value() == "BLUE");
REQUIRE(magic_enum::enum_to_string<cm[1]>().value() == "GREEN");
REQUIRE(!magic_enum::enum_to_string<static_cast<Color>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value());
constexpr Numbers no = Numbers::one;
REQUIRE(magic_enum::enum_to_string<no>().value() == "one");
REQUIRE(magic_enum::enum_to_string<Numbers::two>().value() == "two");
REQUIRE(magic_enum::enum_to_string<Numbers::three>().value() == "three");
REQUIRE(!magic_enum::enum_to_string<static_cast<Numbers>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value());
constexpr Directions dr = Directions::Right;
REQUIRE(magic_enum::enum_to_string<Directions::Up>().value() == "Up");
REQUIRE(magic_enum::enum_to_string<Directions::Down>().value() == "Down");
REQUIRE(magic_enum::enum_to_string<dr>().value() == "Right");
REQUIRE(magic_enum::enum_to_string<Directions::Left>().value() == "Left");
REQUIRE(!magic_enum::enum_to_string<static_cast<Directions>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value());
constexpr number nt = number::three;
REQUIRE(magic_enum::enum_to_string<number::one>().value() == "one");
REQUIRE(magic_enum::enum_to_string<number::two>().value() == "two");
REQUIRE(magic_enum::enum_to_string<nt>().value() == "three");
REQUIRE(!magic_enum::enum_to_string<static_cast<number>(MAGIC_ENUM_MAX_SEARCH_DEPTH)>().has_value());
}
TEST_CASE("magic_enum::enum_from_string(name)") {
REQUIRE(magic_enum::enum_from_string<Color>("RED").value() == Color::RED);
REQUIRE(magic_enum::enum_from_string<Color>("GREEN").value() == Color::GREEN);
REQUIRE(magic_enum::enum_from_string<Color>("BLUE").value() == Color::BLUE);
REQUIRE(!magic_enum::enum_from_string<Color>("None").has_value());
REQUIRE(magic_enum::enum_from_string<Numbers>("one").value() == Numbers::one);
REQUIRE(magic_enum::enum_from_string<Numbers>("two").value() == Numbers::two);
REQUIRE(magic_enum::enum_from_string<Numbers>("two").value() == Numbers::two);
REQUIRE(!magic_enum::enum_from_string<Numbers>("None").has_value());
REQUIRE(magic_enum::enum_from_string<Directions>("Up").value() == Directions::Up);
REQUIRE(magic_enum::enum_from_string<Directions>("Down").value() == Directions::Down);
REQUIRE(magic_enum::enum_from_string<Directions>("Right").value() == Directions::Right);
REQUIRE(magic_enum::enum_from_string<Directions>("Left").value() == Directions::Left);
REQUIRE(!magic_enum::enum_from_string<Directions>("None").has_value());
REQUIRE(magic_enum::enum_from_string<number>("one").value() == number::one);
REQUIRE(magic_enum::enum_from_string<number>("two").value() == number::two);
REQUIRE(magic_enum::enum_from_string<number>("two").value() == number::two);
REQUIRE(!magic_enum::enum_from_string<number>("None").has_value());
}