diff --git a/.vscode/settings.json b/.vscode/settings.json
index abcce64..1499450 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,6 +1,10 @@
{
- "files.associations": {
- "cmath": "cpp",
- "string_view": "cpp"
- }
-}
\ No newline at end of file
+ "files.associations": {
+ "cmath": "cpp",
+ "string_view": "cpp",
+ "sstream": "cpp",
+ "optional": "cpp",
+ "memory": "cpp",
+ "random": "cpp"
+ }
+}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 10a4c73..4a073e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,15 +1,17 @@
cmake_minimum_required(VERSION 3.14)
-project(enum_name_example VERSION 0.1 LANGUAGES CXX)
+project(
+ enum_name_example
+ VERSION 0.1
+ LANGUAGES CXX)
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
include(FetchContent)
FetchContent_Declare(
- DocTest
- GIT_REPOSITORY "https://github.com/onqtam/doctest"
- GIT_TAG "v2.4.11"
-)
+ DocTest
+ GIT_REPOSITORY "https://github.com/onqtam/doctest"
+ GIT_TAG "v2.4.11")
FetchContent_MakeAvailable(DocTest)
@@ -17,4 +19,4 @@ add_executable(${PROJECT_NAME} example/main.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/include)
enable_testing()
-add_subdirectory(test)
\ No newline at end of file
+add_subdirectory(test)
diff --git a/README.md b/README.md
index 523b10c..ac10478 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,11 @@ Converting (scoped)enum values to/from string names written in C++>=11.
## Features
* Supports `enum` and `enum class`
* Supports enums in namespaces, classes or structs even templated or not
-* Supports compile-time as much as possible using with C++14 and later
+* Supports compile-time as much as possible using with C++17 and later
* Changing enum range with template parameter (default range: `[0, 256)`) on each call or with your special function for types or adding specialized `enum_range` struct
* Supports and automatically overloaded `operator<<` for Enum types to direct using with ostream objects
* Supports custom enum name output by explicit specialization of `constexpr inline auto mgutility::detail::enum_type::name() noexcept` function
+* Supports bitmasked enums and auto detect them
* Supports iterate over enum (names and values) with `mgutility::enum_for_each()` class and it is compatible with standard ranges and views
## Limitations
@@ -20,16 +21,32 @@ Converting (scoped)enum values to/from string names written in C++>=11.
* Wider range can increase compile time so user responsible to adjusting for enum's range
-## Usage ([try it!](https://godbolt.org/z/YM5EvY1Y5))
+## Usage ([try it!](https://godbolt.org/z/dfeYxscvT))
```C++
#include
#include "enum_name.hpp"
-num class rgb_color { red, green, blue, unknown = -1 };
+enum class rgb_color {
+ red = 1 << 0,
+ green = 1 << 1,
+ blue = 1 << 2,
+ unknown = -1
+};
+
+auto operator|(rgb_color lhs, rgb_color rhs) -> rgb_color {
+ return static_cast(mgutility::enum_to_underlying(lhs) |
+ mgutility::enum_to_underlying(rhs));
+}
+
+auto operator&(rgb_color lhs, rgb_color rhs) -> rgb_color {
+ return static_cast(mgutility::enum_to_underlying(lhs) &
+ mgutility::enum_to_underlying(rhs));
+}
// specialize rgb_color::unknown to make output "UNKNOWN" instead of "unknown"
template <>
-constexpr auto mgutility::detail::enum_type::name() noexcept
+constexpr inline auto
+mgutility::detail::enum_type::name() noexcept
-> string_view {
return "UNKNOWN";
}
@@ -38,38 +55,41 @@ constexpr auto mgutility::detail::enum_type::name
template <>
struct mgutility::enum_range {
static constexpr auto min = -1;
- static constexpr auto max = 3;
+ static constexpr auto max = 5;
};
// you can specialize enum ranges with overload per enum types (option 2)
-auto enum_name = [](rgb_color c) { return mgutility::enum_name<-1, 3>(c); };
+auto enum_name = [](rgb_color c) { return mgutility::enum_name<-1, 5>(c); };
#if defined(__cpp_lib_print)
#include
#include
#endif
-
int main() {
auto x = rgb_color::blue;
- auto y = mgutility::to_enum("greenn");
+ auto y = mgutility::to_enum("green|red");
#if defined(__cpp_lib_print)
-// enum_for_each can usable with views and range algorithms
-auto colors = mgutility::enum_for_each() |
- std::ranges::views::filter(
- [](auto &&pair) { return pair.second != "UNKNOWN"; });
+ // enum_for_each can usable with views and range algorithms
+ auto colors = mgutility::enum_for_each() |
+ std::ranges::views::filter([](auto &&pair) {
+ return !pair.second.empty() && pair.second != "UNKNOWN";
+ });
std::ranges::for_each(colors, [](auto &&color) {
- std::println("{} \t: {}", color.second, mgutility::enum_to_underlying(color.first));
+ std::println("{} \t: {}", color.second,
+ mgutility::enum_to_underlying(color.first));
});
#else
for (auto&& e : mgutility::enum_for_each()) {
- if(e.second != "UNKNOWN"){
- std::cout << e.second << " \t: " << mgutility::enum_to_underlying(e.first) << '\n';
+ if (!e.second.empty() && e.second != "UNKNOWN") {
+ std::cout << e.second
+ << " \t: " << mgutility::enum_to_underlying(e.first)
+ << '\n';
}
// std::pair {enum_type, name_of_enum}
}
@@ -78,8 +98,6 @@ auto colors = mgutility::enum_for_each() |
// default signature: enum_name(Enum&&) Changing max_value to not too much greater than enum's
// max value, it will compiles faster
- std::cout << mgutility::enum_name(x) << '\n'; // will print "blue" to output
- // or
std::cout << x << '\n'; // will print "blue" to output
// calling specialized enum ranges function for rgb_color type
diff --git a/example/main.cpp b/example/main.cpp
index 4f0b051..206cb30 100644
--- a/example/main.cpp
+++ b/example/main.cpp
@@ -1,33 +1,31 @@
-#include
#include "enum_name.hpp"
+#include
+enum class rgb_color { red, green, blue, unknown = -1 };
-enum class rgb_color { red, green, blue, unknown = -1};
-
-// you can specialize enum ranges with specialize struct per enum types (option 1)
-namespace mgutility{
- template<>
- struct enum_range
- {
- static constexpr auto min = -1;
- static constexpr auto max = 3;
- };
-}
+// you can specialize enum ranges with specialize struct per enum types (option
+// 1)
+namespace mgutility {
+template <> struct enum_range {
+ static constexpr auto min = -1;
+ static constexpr auto max = 3;
+};
+} // namespace mgutility
// you can specialize enum ranges with overload per enum types (option 2)
-auto enum_name = [](rgb_color c){ return mgutility::enum_name<-1, 3>(c); };
+auto enum_name = [](rgb_color c) { return mgutility::enum_name<-1, 3>(c); };
+
+int main() {
+ auto x = rgb_color::blue;
+ auto y = mgutility::to_enum("green");
+ // default signature: enum_name(Enum&&) Changing max_value to not too much greater than enum's
+ // max value, it will compiles faster
+ std::cout << mgutility::enum_name(x) << '\n'; // will print "blue" to output
-int main()
-{
- auto x = rgb_color::blue;
- auto y = mgutility::to_enum("green");
-
- // default signature: enum_name(Enum&&)
- // Changing max_value to not too much greater than enum's max value, it will compiles faster
- std::cout << mgutility::enum_name(x) << '\n'; // will print "blue" to output
-
- // calling specialized enum ranges function for rgb_color type
- // will print "green" to output, if y can't convert to rgb_color prints "unknown"
- std::cout << enum_name(y.value_or(rgb_color::unknown)) << '\n';
+ // calling specialized enum ranges function for rgb_color type
+ // will print "green" to output, if y can't convert to rgb_color prints
+ // "unknown"
+ std::cout << enum_name(y.value_or(rgb_color::unknown)) << '\n';
}
\ No newline at end of file
diff --git a/include/enum_name.hpp b/include/enum_name.hpp
index c7ed6ab..691c4c7 100644
--- a/include/enum_name.hpp
+++ b/include/enum_name.hpp
@@ -33,7 +33,6 @@
#include
#include
#include
-#include
#if defined(_MSC_VER) && _MSC_VER < 1910
#error "Requires MSVC 2017 or newer!"
@@ -59,6 +58,18 @@
#error "Standards older than C++11 is not supported!"
#endif
+#if MG_ENUM_NAME_CPLUSPLUS > 201703L && !defined(__clang__)
+#define MG_ENUM_NAME_CNSTXPR_FUNC constexpr
+#else
+#define MG_ENUM_NAME_CNSTXPR_FUNC
+#endif
+
+#if MG_ENUM_NAME_CPLUSPLUS > 201703L
+#define MG_ENUM_NAME_CNSTEVL consteval
+#else
+#define MG_ENUM_NAME_CNSTEVL
+#endif
+
#if MG_ENUM_NAME_CPLUSPLUS > 201702L
#include
#endif
@@ -66,12 +77,17 @@
namespace mgutility {
namespace detail {
-template
-struct is_scoped_enum {
- static constexpr auto value =
- std::is_enum::value &&
- !std::is_convertible::type>::value;
+template struct is_scoped_enum {
+ static constexpr auto value =
+ std::is_enum::value &&
+ !std::is_convertible::type>::value;
};
+
+template struct has_bit_or : std::false_type {};
+
+template
+struct has_bit_or : std::true_type {};
+
#if MG_ENUM_NAME_CPLUSPLUS > 201103L
template
static constexpr bool is_scoped_enum_v = is_scoped_enum::value;
@@ -88,217 +104,225 @@ using remove_const_t = typename std::remove_const::type;
template
using enable_if_t = typename std::enable_if::type;
-constexpr auto strlen_constexpr(const char* str,
- size_t sz = 0) noexcept -> size_t {
- return str[sz] == '\0' ? sz : strlen_constexpr(str, ++sz);
+constexpr auto strlen_constexpr(const char *str, size_t sz = 0) noexcept
+ -> size_t {
+ return str[sz] == '\0' ? sz : strlen_constexpr(str, ++sz);
}
-template
-class basic_string_view {
- public:
- constexpr inline basic_string_view() noexcept : data_(""), size_(0) {}
- constexpr inline basic_string_view(const Char* str) noexcept
- : data_(str), size_(strlen_constexpr(str)) {}
- constexpr inline basic_string_view(const Char* str, size_t len) noexcept
- : data_(str), size_(len) {}
- constexpr inline basic_string_view(const basic_string_view& other)
- : data_(other.data_), size_(other.size_) {}
- constexpr inline basic_string_view(basic_string_view&& other) noexcept
- : data_(std::move(other.data_)), size_(std::move(other.size_)) {}
- MG_ENUM_NAME_CNSTXPR inline basic_string_view& operator=(
- const basic_string_view& other) noexcept {
- data_ = other.data_;
- size_ = other.size_;
- return *this;
- }
- MG_ENUM_NAME_CNSTXPR inline basic_string_view& operator=(
- basic_string_view&& other) noexcept {
- data_ = std::move(other.data_);
- size_ = std::move(other.size_);
- return *this;
- }
- constexpr inline const Char operator[](size_t index) const noexcept {
- return data_[index];
- }
- constexpr inline const Char* begin() const noexcept { return data_; }
- constexpr inline const Char* end() const noexcept {
- return (data_ + size_);
- }
- constexpr inline bool empty() const noexcept { return size_ < 1; }
- constexpr inline size_t size() const noexcept { return size_; }
- constexpr inline const Char* data() const noexcept { return data_; }
- constexpr inline basic_string_view substr(size_t begin,
- size_t len) const noexcept {
- return basic_string_view(data_ + begin, len);
- }
- constexpr inline size_t rfind(Char c, size_t pos = 0) const noexcept {
- return c == data_[pos] ? pos : rfind(c, --pos);
- }
-
- constexpr friend inline bool operator==(
- basic_string_view lhs, basic_string_view rhs) noexcept {
- return (lhs.size_ == rhs.size_) &&
- std::strncmp(lhs.data_, rhs.data_, lhs.size_) == 0;
- }
-
- constexpr friend inline bool operator==(basic_string_view lhs,
- const Char* rhs) noexcept {
- return (lhs.size_ == strlen_constexpr(rhs)) &&
- std::strncmp(lhs.data_, rhs, lhs.size_) == 0;
+template class basic_string_view {
+public:
+ constexpr inline basic_string_view() noexcept : data_(""), size_(0) {}
+ constexpr inline basic_string_view(const Char *str) noexcept
+ : data_(str), size_(strlen_constexpr(str)) {}
+ constexpr inline basic_string_view(const Char *str, size_t len) noexcept
+ : data_(str), size_(len) {}
+ constexpr inline basic_string_view(const basic_string_view &other)
+ : data_(other.data_), size_(other.size_) {}
+ constexpr inline basic_string_view(basic_string_view &&other) noexcept
+ : data_(std::move(other.data_)), size_(std::move(other.size_)) {}
+ MG_ENUM_NAME_CNSTXPR inline basic_string_view &
+ operator=(const basic_string_view &other) noexcept {
+ data_ = other.data_;
+ size_ = other.size_;
+ return *this;
+ }
+ MG_ENUM_NAME_CNSTXPR inline basic_string_view &
+ operator=(basic_string_view &&other) noexcept {
+ data_ = std::move(other.data_);
+ size_ = std::move(other.size_);
+ return *this;
+ }
+ constexpr inline const Char operator[](size_t index) const noexcept {
+ return data_[index];
+ }
+ constexpr inline const Char *begin() const noexcept { return data_; }
+ constexpr inline const Char *end() const noexcept { return (data_ + size_); }
+ constexpr inline bool empty() const noexcept { return size_ < 1; }
+ constexpr inline size_t size() const noexcept { return size_; }
+ constexpr inline const Char *data() const noexcept { return data_; }
+ constexpr inline basic_string_view substr(size_t begin,
+ size_t len) const noexcept {
+ return basic_string_view(data_ + begin, len);
+ }
+ constexpr inline size_t rfind(Char c, size_t pos = npos) const noexcept {
+ return (pos == npos ? pos = size_ : pos = pos), c == data_[pos] ? pos
+ : pos == 0U
+ ? npos
+ : rfind(c, --pos);
+ }
+ constexpr inline size_t find(Char c, size_t pos = 0) const noexcept {
+ return c == data_[pos] ? pos : pos < size_ ? find(c, ++pos) : npos;
+ }
+
+ constexpr friend inline bool
+ operator==(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return (lhs.size_ == rhs.size_) &&
+ std::strncmp(lhs.data_, rhs.data_, lhs.size_) == 0;
+ }
+
+ constexpr friend inline bool operator==(basic_string_view lhs,
+ const Char *rhs) noexcept {
+ return (lhs.size_ == strlen_constexpr(rhs)) &&
+ std::strncmp(lhs.data_, rhs, lhs.size_) == 0;
+ }
+
+ constexpr friend inline bool
+ operator!=(basic_string_view lhs,
+ basic_string_view rhs) noexcept {
+ return !(lhs == rhs);
+ }
+
+ constexpr friend inline bool operator!=(basic_string_view lhs,
+ const Char *rhs) noexcept {
+ return !(lhs == rhs);
+ }
+
+ inline operator std::string() { return std::string(data_, size_); }
+ inline operator std::string() const { return std::string(data_, size_); }
+
+ friend inline std::ostream &operator<<(std::ostream &os,
+ const basic_string_view &sv) {
+ for (auto c : sv) {
+ os << c;
}
+ return os;
+ }
- constexpr friend inline bool operator!=(
- basic_string_view lhs, basic_string_view rhs) noexcept {
- return !(lhs == rhs);
- }
-
- constexpr friend inline bool operator!=(basic_string_view lhs,
- const Char* rhs) noexcept {
- return !(lhs == rhs);
- }
-
- inline operator std::string() { return std::string(data_, size_); }
- inline operator std::string() const { return std::string(data_, size_); }
-
- friend inline std::ostream& operator<<(std::ostream& os,
- const basic_string_view& sv) {
- for (auto c : sv) {
- os << c;
- }
- return os;
- }
+ static constexpr auto npos = -1;
- private:
- size_t size_;
- const Char* data_;
+private:
+ size_t size_;
+ const Char *data_;
};
using string_view = basic_string_view;
struct bad_optional_access : public std::exception {
- const char* what() const noexcept { return "optional has no value"; }
+ const char *what() const noexcept { return "optional has no value"; }
};
struct nullopt_t;
-template
-class optional {
- public:
- MG_ENUM_NAME_CNSTXPR inline optional(nullopt_t&)
- : dummy_{0}, has_value_{false} {}
- MG_ENUM_NAME_CNSTXPR inline optional() : dummy_{0}, has_value_{false} {}
- template
- MG_ENUM_NAME_CNSTXPR inline optional(Args&&... args)
- : value_{T{std::forward(args)...}}, has_value_{true} {}
- MG_ENUM_NAME_CNSTXPR inline optional(T&& value)
- : value_{value}, has_value_{true} {}
- MG_ENUM_NAME_CNSTXPR inline optional(const optional& other)
- : value_{other.value_}, has_value_{other.has_value_} {}
- MG_ENUM_NAME_CNSTXPR inline optional(optional&& other)
- : value_{other.value_}, has_value_{other.has_value_} {
- other.reset();
- }
- inline ~optional() { has_value_ = false; }
- MG_ENUM_NAME_CNSTXPR inline optional& operator=(const optional& other) {
- value_ = other.value_;
- has_value_ = other.has_value_;
- return *this;
- }
- MG_ENUM_NAME_CNSTXPR inline optional& operator=(optional&& other) {
- value_ = other.value_;
- has_value_ = other.has_value_;
- other.reset();
- return *this;
- }
- MG_ENUM_NAME_CNSTXPR inline void swap(optional&& other) {
- auto val = std::move(other.value_);
- other.value_ = std::move(value_);
- value_ = std::move(val);
-
- auto hval = std::move(other.has_value_);
- other.has_value_ = std::move(has_value_);
- has_value_ = std::move(hval);
- }
- MG_ENUM_NAME_CNSTXPR inline T& operator*() { return value_; }
- MG_ENUM_NAME_CNSTXPR inline T& operator*() const { return value_; }
- MG_ENUM_NAME_CNSTXPR inline T& value() {
- if (!has_value_) throw detail::bad_optional_access();
- return value_;
- }
- MG_ENUM_NAME_CNSTXPR inline T& value() const {
- if (!has_value_) throw detail::bad_optional_access();
- return value_;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(T&& value) {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(T&& value) const {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(const T& value) {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline T value_or(const T& value) const {
- return has_value_ ? value_ : value;
- }
- MG_ENUM_NAME_CNSTXPR inline void emplace(T value) {
- value_ = std::move(value);
- has_value_ = true;
- }
- template
- MG_ENUM_NAME_CNSTXPR inline void emplace(Args&&... args) {
- value_ = std::move(T{std::forward(args)...});
- has_value_ = true;
- }
- MG_ENUM_NAME_CNSTXPR inline bool has_value() const { return has_value_; }
-
-#if !(defined(__clang__) && __clang_major__ < 11)
- template ::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR inline void reset() {
- T::~T();
- has_value_ = false;
- }
-#endif
- template ::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR inline void reset() {
- value_ = T{};
- has_value_ = false;
- }
-
- MG_ENUM_NAME_CNSTXPR operator bool() { return has_value_; }
-
- private:
- union {
- T value_;
- char dummy_[sizeof(T)];
- };
- bool has_value_;
+template class optional {
+public:
+ MG_ENUM_NAME_CNSTXPR inline optional(nullopt_t &)
+ : dummy_{0}, has_value_{false} {}
+ MG_ENUM_NAME_CNSTXPR inline optional() : dummy_{0}, has_value_{false} {}
+ template
+ MG_ENUM_NAME_CNSTXPR inline optional(Args &&...args)
+ : value_{T{std::forward(args)...}}, has_value_{true} {}
+ MG_ENUM_NAME_CNSTXPR inline optional(T &&value)
+ : value_{value}, has_value_{true} {}
+ MG_ENUM_NAME_CNSTXPR inline optional(const optional &other)
+ : value_{other.value_}, has_value_{other.has_value_} {}
+ MG_ENUM_NAME_CNSTXPR inline optional(optional &&other)
+ : value_{other.value_}, has_value_{other.has_value_} {
+ other.reset();
+ }
+ inline ~optional() { has_value_ = false; }
+ MG_ENUM_NAME_CNSTXPR inline optional &operator=(const optional &other) {
+ value_ = other.value_;
+ has_value_ = other.has_value_;
+ return *this;
+ }
+ MG_ENUM_NAME_CNSTXPR inline optional &operator=(optional &&other) {
+ value_ = other.value_;
+ has_value_ = other.has_value_;
+ other.reset();
+ return *this;
+ }
+ MG_ENUM_NAME_CNSTXPR inline void swap(optional &&other) {
+ auto val = std::move(other.value_);
+ other.value_ = std::move(value_);
+ value_ = std::move(val);
+
+ auto hval = std::move(other.has_value_);
+ other.has_value_ = std::move(has_value_);
+ has_value_ = std::move(hval);
+ }
+ MG_ENUM_NAME_CNSTXPR inline T &operator*() { return value_; }
+ MG_ENUM_NAME_CNSTXPR inline T &operator*() const { return value_; }
+ MG_ENUM_NAME_CNSTXPR inline T &value() {
+ if (!has_value_)
+ throw detail::bad_optional_access();
+ return value_;
+ }
+ MG_ENUM_NAME_CNSTXPR inline T &value() const {
+ if (!has_value_)
+ throw detail::bad_optional_access();
+ return value_;
+ }
+ MG_ENUM_NAME_CNSTXPR inline T value_or(T &&value) {
+ return has_value_ ? value_ : value;
+ }
+ MG_ENUM_NAME_CNSTXPR inline T value_or(T &&value) const {
+ return has_value_ ? value_ : value;
+ }
+ MG_ENUM_NAME_CNSTXPR inline T value_or(const T &value) {
+ return has_value_ ? value_ : value;
+ }
+ MG_ENUM_NAME_CNSTXPR inline T value_or(const T &value) const {
+ return has_value_ ? value_ : value;
+ }
+ MG_ENUM_NAME_CNSTXPR inline void emplace(T value) {
+ value_ = std::move(value);
+ has_value_ = true;
+ }
+ template
+ MG_ENUM_NAME_CNSTXPR inline void emplace(Args &&...args) {
+ value_ = std::move(T{std::forward(args)...});
+ has_value_ = true;
+ }
+ MG_ENUM_NAME_CNSTXPR inline bool has_value() const { return has_value_; }
+
+ template ::value, bool> = true>
+ MG_ENUM_NAME_CNSTXPR inline void reset() {
+ value_ = T{};
+ has_value_ = false;
+ }
+
+ template ::value, bool> = true>
+ MG_ENUM_NAME_CNSTXPR inline void reset() {
+ value_.~T();
+ has_value_ = false;
+ }
+
+ MG_ENUM_NAME_CNSTXPR operator bool() { return has_value_; }
+
+private:
+ union {
+ T value_;
+ char dummy_[sizeof(T)];
+ };
+ bool has_value_;
};
struct nullopt_t {
- template
- MG_ENUM_NAME_CNSTXPR operator optional() {
- return optional{};
- }
+ template MG_ENUM_NAME_CNSTXPR operator optional() {
+ return optional{};
+ }
};
auto nullopt = nullopt_t{};
#else
-template
-using optional = std::optional;
+template using optional = std::optional;
inline constexpr auto nullopt{std::nullopt};
using string_view = std::string_view;
-template
-using enable_if_t = std::enable_if_t;
+template using enable_if_t = std::enable_if_t;
#endif
-template
-struct enum_sequence {};
+template
+using string_or_view_t =
+ typename std::conditional::value, std::string,
+ detail::string_view>::type;
+
+template struct enum_sequence {};
template
struct enum_sequence_helper
@@ -306,7 +330,7 @@ struct enum_sequence_helper
template
struct enum_sequence_helper {
- using type = enum_sequence(Next)...>;
+ using type = enum_sequence(Next)...>;
};
template
@@ -316,189 +340,295 @@ struct enum_type {
#if defined(_MSC_VER)
#define __PRETTY_FUNCTION__ __FUNCSIG__
#endif
- template <
- typename Enum, Enum e,
- detail::enable_if_t::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR static inline auto name() noexcept
- -> detail::string_view {
- auto str = detail::string_view(__PRETTY_FUNCTION__);
- auto offset{lastidxenumname[0] + lastidxenumname[1]};
- auto index =
- std::max(str.rfind(lastidxenumname[2], str.size() - offset),
- str.rfind(lastidxenumname[3], str.size() - offset));
- auto result = str.substr(index + 1, str.size() - offset - index);
- return result[0] == '(' ? "" : result;
- }
-
- template <
- typename Enum, Enum e,
- detail::enable_if_t::value, bool> = true>
- MG_ENUM_NAME_CNSTXPR static inline auto name() noexcept
- -> detail::string_view {
- auto str = detail::string_view(__PRETTY_FUNCTION__);
- auto index =
- str.rfind(lastidxenumname[3], str.size() - lastidxenumname[0]) + 1;
- auto result =
- str.substr(index, str.size() - lastidxenumname[0] - index);
- return result.size() > 4 ? result[4] == lastidxenumname[4] ? "" : result
- : result;
- }
-
- private:
- static constexpr int lastidxenumname[] =
+ template <
+ typename Enum, Enum e,
+ detail::enable_if_t::value, bool> = true>
+ MG_ENUM_NAME_CNSTXPR static inline auto name() noexcept
+ -> detail::string_view {
+ auto str = detail::string_view(__PRETTY_FUNCTION__);
+ auto offset{lastidxenumname[0] + lastidxenumname[1]};
+ auto index = std::max(str.rfind(lastidxenumname[2], str.size() - offset),
+ str.rfind(lastidxenumname[3], str.size() - offset));
+ auto result = str.substr(index + 1, str.size() - offset - index);
+ return result[0] == '(' ? "" : result;
+ }
+
+ template <
+ typename Enum, Enum e,
+ detail::enable_if_t::value, bool> = true>
+ MG_ENUM_NAME_CNSTXPR static inline auto name() noexcept
+ -> detail::string_view {
+ auto str = detail::string_view(__PRETTY_FUNCTION__);
+ auto index =
+ str.rfind(lastidxenumname[3], str.size() - lastidxenumname[0]) + 1;
+ auto result = str.substr(index, str.size() - lastidxenumname[0] - index);
+ return result.size() > 4 ? result[4] == lastidxenumname[4] ? "" : result
+ : result;
+ }
+
+private:
+ static constexpr int lastidxenumname[] =
#if defined(_MSC_VER)
- {22, 0, ',', ':', '<'};
+ {21, 0, ',', ':', '<'};
#elif defined(__clang__)
- {1, 1, ' ', ':', '('};
+ {1, 1, ' ', ':', '('};
#elif defined(__GNUC__)
- {
+ {
#if MG_ENUM_NAME_CPLUSPLUS < 201703L
- 179,
+ 179,
#else
- 165,
+ 165,
#endif
- 5, ' ', ':', '('};
+ 5, ' ', ':', '('};
#endif
};
template
-using enum_pair = std::pair;
+using enum_pair = std::pair>;
template
-inline auto get_enum_array(detail::enum_sequence) noexcept
+MG_ENUM_NAME_CNSTXPR inline auto
+get_enum_array(detail::enum_sequence) noexcept
-> std::array {
- static std::array
- arr{"", enum_type::template name()...};
- return arr;
+ return std::array{
+ "", enum_type::template name()...};
}
template
-inline auto to_enum_impl(detail::string_view str) noexcept
+MG_ENUM_NAME_CNSTXPR inline auto to_enum_impl(detail::string_view str) noexcept
-> detail::optional {
- auto arr = get_enum_array(detail::make_enum_sequence());
- const auto index{std::find(arr.begin() + 1, arr.end(), str)};
- return index == arr.end()
- ? detail::nullopt
- : detail::optional{static_cast(
- std::distance(arr.begin(), index) + Min - 1)};
+ MG_ENUM_NAME_CNSTXPR auto arr =
+ get_enum_array(detail::make_enum_sequence());
+ const auto index{std::find(arr.begin() + 1, arr.end(), str)};
+ return index == arr.end() ? detail::nullopt
+ : detail::optional{static_cast(
+ std::distance(arr.begin(), index) + Min - 1)};
}
template
-inline auto enum_name_impl(Enum e) noexcept -> detail::string_view {
- auto arr = get_enum_array(detail::make_enum_sequence());
- const auto index{std::abs(Min) + static_cast(e) + (Min < 0 ? 1 : 1)};
- return arr[(index < Min || index > arr.size() - 1) ? 0 : index];
+MG_ENUM_NAME_CNSTXPR inline auto
+to_enum_bitmask_impl(detail::string_view str) noexcept
+ -> detail::optional {
+ if (str.find('|') == detail::string_view::npos) {
+ return to_enum_impl(str);
+ } else {
+ auto index = std::size_t{};
+ auto result = detail::optional{detail::nullopt};
+ for (std::size_t i{}; i < str.size(); ++i) {
+ if (str[i] == '|') {
+ const auto name = str.substr(index, i - index);
+ auto maybe_enum =
+ to_enum_impl(str.substr(index, i - index));
+ if (!name.empty() && maybe_enum) {
+ result.emplace(result ? static_cast(*result | *maybe_enum)
+ : *maybe_enum);
+ }
+
+ index = i + 1U;
+ }
+ }
+ if (result) {
+ auto maybe_enum =
+ to_enum_impl(str.substr(index, str.size() - index));
+ if (maybe_enum) {
+ result.emplace(static_cast(*result | *maybe_enum));
+ } else {
+ result.reset();
+ }
+ }
+
+ return result;
+ }
+}
+
+template ::value, bool> = true>
+MG_ENUM_NAME_CNSTXPR inline auto enum_name_impl(Enum e) noexcept
+ -> detail::string_view {
+ MG_ENUM_NAME_CNSTXPR auto arr =
+ get_enum_array(detail::make_enum_sequence());
+ const auto index{(Min < 0 ? Min * -1 : Min) + static_cast(e) +
+ (Min < 0 ? 1 : 1)};
+ return arr[(index < Min || index > arr.size() - 1) ? 0 : index];
+}
+
+template ::value, bool> = true>
+MG_ENUM_NAME_CNSTXPR_FUNC inline auto enum_name_impl(Enum e) noexcept
+ -> detail::string_or_view_t {
+ MG_ENUM_NAME_CNSTXPR auto arr =
+ get_enum_array(detail::make_enum_sequence());
+ const auto index{(Min < 0 ? Min * -1 : Min) + static_cast(e) +
+ (Min < 0 ? 1 : 1)};
+ const auto name = arr[(index < Min || index > arr.size() - 1) ? 0 : index];
+
+ const auto isdigit = [](char c) {
+ return static_cast(c) < 58 && static_cast(c) > 47;
+ };
+
+ if (!name.empty() && !isdigit(name[0])) {
+ return std::string{name};
+ } else {
+ auto bitmasked_name = std::string{};
+
+ for (auto i{Min}; i < Max; ++i) {
+ const auto idx = (Min < 0 ? Min * -1 : Min) + i + (Min < 0 ? 1 : 1);
+ if (!(idx < Min || idx > arr.size() - 1) && !arr[idx].empty() &&
+ !isdigit(arr[idx][0]) &&
+ (e & static_cast(i)) == static_cast(i)) {
+ bitmasked_name.append(arr[idx]).append("|");
+ }
+ }
+
+ const auto result = bitmasked_name.substr(0U, bitmasked_name.size() - 1U);
+ return result.find('|') != std::string::npos ? result : std::string{""};
+ }
}
-} // namespace detail
-} // namespace mgutility
+} // namespace detail
+} // namespace mgutility
namespace mgutility {
-template
-struct enum_range {
- static constexpr auto min{-128};
- static constexpr auto max{128};
+template struct enum_range {
+ static constexpr auto min{-128};
+ static constexpr auto max{128};
};
-template
-class enum_for_each {
- using value_type = const detail::enum_pair;
- using size_type = std::size_t;
-
- struct enum_iter {
- using const_iter_type = decltype(enum_range::min);
- using iter_type = detail::remove_const_t;
- using iterator_category = std::forward_iterator_tag;
- using value_type = const detail::enum_pair;
- using difference_type = std::ptrdiff_t;
- using pointer = value_type*;
- using reference = value_type&;
-
- enum_iter() : m_pos{} {}
- enum_iter(iter_type value) : m_pos{value} {}
-
- auto operator++() -> enum_iter& {
- ++m_pos;
- return *this;
- }
+template class enum_for_each {
+ using value_type = const detail::enum_pair;
+ using size_type = std::size_t;
- auto operator++(int) -> enum_iter {
- m_pos++;
- return *this;
- }
+ struct enum_iter {
+ using const_iter_type = decltype(enum_range::min);
+ using iter_type = detail::remove_const_t;
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const detail::enum_pair;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type *;
+ using reference = value_type &;
- auto operator!=(const enum_iter& other) const -> bool {
- return m_pos != other.m_pos;
- }
+ enum_iter() : m_pos{} {}
+ enum_iter(iter_type value) : m_pos{value} {}
- auto operator==(const enum_iter& other) const -> bool {
- return m_pos == other.m_pos;
- }
+ auto operator++() -> enum_iter & {
+ ++m_pos;
+ return *this;
+ }
- auto operator*() const -> value_type;
+ auto operator++(int) -> enum_iter {
+ m_pos++;
+ return *this;
+ }
- private:
- iter_type m_pos;
- };
+ auto operator!=(const enum_iter &other) const -> bool {
+ return m_pos != other.m_pos;
+ }
- public:
- enum_for_each() {}
- auto begin() -> enum_iter& { return m_begin; }
- auto end() -> enum_iter& { return m_end; }
- auto size() -> std::size_t {
- return enum_range::max - enum_range::min;
+ auto operator==(const enum_iter &other) const -> bool {
+ return m_pos == other.m_pos;
}
- private:
- enum_iter m_begin{enum_range::min};
- enum_iter m_end{enum_range::max};
+ auto operator*() const -> value_type;
+
+ private:
+ iter_type m_pos;
+ };
+
+public:
+ enum_for_each() {}
+ auto begin() -> enum_iter & { return m_begin; }
+ auto end() -> enum_iter & { return m_end; }
+ auto size() -> std::size_t {
+ return enum_range::max - enum_range::min;
+ }
+
+private:
+ enum_iter m_begin{enum_range::min};
+ enum_iter m_end{enum_range::max};
};
template
constexpr inline auto enum_to_underlying(Enum e) noexcept
-> detail::underlying_type_t {
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- return static_cast>(e);
+ static_assert(std::is_enum::value, "Value is not an Enum type!");
+ return static_cast>(e);
}
template
MG_ENUM_NAME_CNSTXPR inline auto enum_name(Enum e) noexcept
- -> detail::string_view {
- static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- return detail::enum_name_impl(e);
+ -> detail::string_or_view_t {
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum::value, "Value is not an Enum type!");
+ return detail::enum_name_impl(e);
}
template ::min,
int Max = enum_range::max>
MG_ENUM_NAME_CNSTXPR inline auto enum_name(Enum e) noexcept
- -> detail::string_view {
- static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- return detail::enum_name_impl(e);
+ -> detail::string_or_view_t {
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum::value, "Value is not an Enum type!");
+ return detail::enum_name_impl(e);
}
template
auto enum_for_each::enum_iter::operator*() const -> value_type {
- auto value = static_cast(m_pos);
- return detail::enum_pair{value, enum_name(value)};
+ auto value = static_cast(m_pos);
+ return detail::enum_pair{value, enum_name(value)};
}
template ::min,
- int Max = enum_range::max>
+ int Max = enum_range::max,
+ detail::enable_if_t::value, bool> = true>
MG_ENUM_NAME_CNSTXPR inline auto to_enum(detail::string_view str) noexcept
-> detail::optional {
- static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
- static_assert(std::is_enum::value, "Type is not an Enum type!");
- return detail::to_enum_impl(str);
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum::value, "Type is not an Enum type!");
+ return detail::to_enum_impl(str);
}
-} // namespace mgutility
+
+template ::min,
+ int Max = enum_range::max,
+ detail::enable_if_t::value, bool> = true>
+MG_ENUM_NAME_CNSTXPR inline auto to_enum(detail::string_view str) noexcept
+ -> detail::optional {
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum::value, "Type is not an Enum type!");
+ return detail::to_enum_bitmask_impl(str);
+}
+
+template ::min,
+ int Max = enum_range::max>
+MG_ENUM_NAME_CNSTXPR inline auto to_enum(int value) noexcept
+ -> detail::optional {
+ static_assert(Min < Max - 1, "Max must be greater than (Min + 1)!");
+ static_assert(std::is_enum::value, "Type is not an Enum type!");
+ if (enum_name(static_cast(value)).empty()) {
+ return detail::nullopt;
+ }
+ return static_cast(value);
+}
+} // namespace mgutility
template ::value, bool>::type = true>
-auto operator<<(std::ostream& os, Enum e) -> std::ostream& {
- static_assert(std::is_enum::value, "Value is not an Enum type!");
- os << mgutility::enum_name(e);
- return os;
+auto operator<<(std::ostream &os, Enum e) -> std::ostream & {
+ static_assert(std::is_enum::value, "Value is not an Enum type!");
+ os << mgutility::enum_name(e);
+ return os;
}
-#endif // MGUTILITY_ENUM_NAME_HPP
+#if defined(__cpp_lib_format)
+
+#include
+
+template
+ requires std::is_enum_v
+struct std::formatter : formatter {
+ auto constexpr format(Enum e, format_context &ctx) const {
+ return formatter::format(mgutility::enum_name(e), ctx);
+ }
+};
+
+#endif
+
+#endif // MGUTILITY_ENUM_NAME_HPP
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3d68426..bcfc230 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,11 +1,14 @@
cmake_minimum_required(VERSION 3.14)
-project(enum_name_test VERSION 0.1 LANGUAGES CXX)
+project(
+ enum_name_test
+ VERSION 0.1
+ LANGUAGES CXX)
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
-include_directories(AFTER PUBLIC ${CMAKE_SOURCE_DIR}/include)
+include_directories(AFTER PUBLIC ${CMAKE_SOURCE_DIR}/include)
add_executable(${PROJECT_NAME} enum_name_test.cpp)
target_link_libraries(${PROJECT_NAME} doctest)
-add_test(NAME enum_name_test COMMAND enum_name_test)
\ No newline at end of file
+add_test(NAME enum_name_test COMMAND enum_name_test)
diff --git a/test/enum_name_test.cpp b/test/enum_name_test.cpp
index 266ddfc..3397995 100644
--- a/test/enum_name_test.cpp
+++ b/test/enum_name_test.cpp
@@ -2,207 +2,209 @@
#include "doctest/doctest.h"
#include "enum_name.hpp"
-
enum class color : uint32_t {
- alice_blue, // rgb(240,248,255)
- antique_white, // rgb(250,235,215)
- aqua, // rgb(0,255,255)
- aquamarine, // rgb(127,255,212)
- azure, // rgb(240,255,255)
- beige, // rgb(245,245,220)
- bisque, // rgb(255,228,196)
- black, // rgb(0,0,0)
- blanched_almond, // rgb(255,235,205)
- blue, // rgb(0,0,255)
- blue_violet, // rgb(138,43,226)
- brown, // rgb(165,42,42)
- burly_wood, // rgb(222,184,135)
- cadet_blue, // rgb(95,158,160)
- chartreuse, // rgb(127,255,0)
- chocolate, // rgb(210,105,30)
- coral, // rgb(255,127,80)
- cornflower_blue, // rgb(100,149,237)
- cornsilk, // rgb(255,248,220)
- crimson, // rgb(220,20,60)
- cyan, // rgb(0,255,255)
- dark_blue, // rgb(0,0,139)
- dark_cyan, // rgb(0,139,139)
- dark_golden_rod, // rgb(184,134,11)
- dark_gray, // rgb(169,169,169)
- dark_green, // rgb(0,100,0)
- dark_khaki, // rgb(189,183,107)
- dark_magenta, // rgb(139,0,139)
- dark_olive_green, // rgb(85,107,47)
- dark_orange, // rgb(255,140,0)
- dark_orchid, // rgb(153,50,204)
- dark_red, // rgb(139,0,0)
- dark_salmon, // rgb(233,150,122)
- dark_sea_green, // rgb(143,188,143)
- dark_slate_blue, // rgb(72,61,139)
- dark_slate_gray, // rgb(47,79,79)
- dark_turquoise, // rgb(0,206,209)
- dark_violet, // rgb(148,0,211)
- deep_pink, // rgb(255,20,147)
- deep_sky_blue, // rgb(0,191,255)
- dim_gray, // rgb(105,105,105)
- dodger_blue, // rgb(30,144,255)
- fire_brick, // rgb(178,34,34)
- floral_white, // rgb(255,250,240)
- forest_green, // rgb(34,139,34)
- fuchsia, // rgb(255,0,255)
- gainsboro, // rgb(220,220,220)
- ghost_white, // rgb(248,248,255)
- gold, // rgb(255,215,0)
- golden_rod, // rgb(218,165,32)
- gray, // rgb(128,128,128)
- green, // rgb(0,128,0)
- green_yellow, // rgb(173,255,47)
- honey_dew, // rgb(240,255,240)
- hot_pink, // rgb(255,105,180)
- indian_red, // rgb(205,92,92)
- indigo, // rgb(75,0,130)
- ivory, // rgb(255,255,240)
- khaki, // rgb(240,230,140)
- lavender, // rgb(230,230,250)
- lavender_blush, // rgb(255,240,245)
- lawn_green, // rgb(124,252,0)
- lemon_chiffon, // rgb(255,250,205)
- light_blue, // rgb(173,216,230)
- light_coral, // rgb(240,128,128)
- light_cyan, // rgb(224,255,255)
- light_golden_rod_yellow, // rgb(250,250,210)
- light_gray, // rgb(211,211,211)
- light_green, // rgb(144,238,144)
- light_pink, // rgb(255,182,193)
- light_salmon, // rgb(255,160,122)
- light_sea_green, // rgb(32,178,170)
- light_sky_blue, // rgb(135,206,250)
- light_slate_gray, // rgb(119,136,153)
- light_steel_blue, // rgb(176,196,222)
- light_yellow, // rgb(255,255,224)
- lime, // rgb(0,255,0)
- lime_green, // rgb(50,205,50)
- linen, // rgb(250,240,230)
- magenta, // rgb(255,0,255)
- maroon, // rgb(128,0,0)
- medium_aquamarine, // rgb(102,205,170)
- medium_blue, // rgb(0,0,205)
- medium_orchid, // rgb(186,85,211)
- medium_purple, // rgb(147,112,219)
- medium_sea_green, // rgb(60,179,113)
- medium_slate_blue, // rgb(123,104,238)
- medium_spring_green, // rgb(0,250,154)
- medium_turquoise, // rgb(72,209,204)
- medium_violet_red, // rgb(199,21,133)
- midnight_blue, // rgb(25,25,112)
- mint_cream, // rgb(245,255,250)
- misty_rose, // rgb(255,228,225)
- moccasin, // rgb(255,228,181)
- navajo_white, // rgb(255,222,173)
- navy, // rgb(0,0,128)
- old_lace, // rgb(253,245,230)
- olive, // rgb(128,128,0)
- olive_drab, // rgb(107,142,35)
- orange, // rgb(255,165,0)
- orange_red, // rgb(255,69,0)
- orchid, // rgb(218,112,214)
- pale_golden_rod, // rgb(238,232,170)
- pale_green, // rgb(152,251,152)
- pale_turquoise, // rgb(175,238,238)
- pale_violet_red, // rgb(219,112,147)
- papaya_whip, // rgb(255,239,213)
- peach_puff, // rgb(255,218,185)
- peru, // rgb(205,133,63)
- pink, // rgb(255,192,203)
- plum, // rgb(221,160,221)
- powder_blue, // rgb(176,224,230)
- purple, // rgb(128,0,128)
- rebecca_purple, // rgb(102,51,153)
- red, // rgb(255,0,0)
- rosy_brown, // rgb(188,143,143)
- royal_blue, // rgb(65,105,225)
- saddle_brown, // rgb(139,69,19)
- salmon, // rgb(250,128,114)
- sandy_brown, // rgb(244,164,96)
- sea_green, // rgb(46,139,87)
- sea_shell, // rgb(255,245,238)
- sienna, // rgb(160,82,45)
- silver, // rgb(192,192,192)
- sky_blue, // rgb(135,206,235)
- slate_blue, // rgb(106,90,205)
- slate_gray, // rgb(112,128,144)
- snow, // rgb(255,250,250)
- spring_green, // rgb(0,255,127)
- steel_blue, // rgb(70,130,180)
- tan, // rgb(210,180,140)
- teal, // rgb(0,128,128)
- thistle, // rgb(216,191,216)
- tomato, // rgb(255,99,71)
- turquoise, // rgb(64,224,208)
- violet, // rgb(238,130,238)
- wheat, // rgb(245,222,179)
- white, // rgb(255,255,255)
- white_smoke, // rgb(245,245,245)
- yellow, // rgb(255,255,0)
- yellow_green // rgb(154,205,50)
-}; // enum class color
-
-namespace mgutility{
- template<>
- struct enum_range
- {
- static constexpr auto min = 0;
- static constexpr auto max = 150;
- };
-}
-
+ alice_blue, // rgb(240,248,255)
+ antique_white, // rgb(250,235,215)
+ aqua, // rgb(0,255,255)
+ aquamarine, // rgb(127,255,212)
+ azure, // rgb(240,255,255)
+ beige, // rgb(245,245,220)
+ bisque, // rgb(255,228,196)
+ black, // rgb(0,0,0)
+ blanched_almond, // rgb(255,235,205)
+ blue, // rgb(0,0,255)
+ blue_violet, // rgb(138,43,226)
+ brown, // rgb(165,42,42)
+ burly_wood, // rgb(222,184,135)
+ cadet_blue, // rgb(95,158,160)
+ chartreuse, // rgb(127,255,0)
+ chocolate, // rgb(210,105,30)
+ coral, // rgb(255,127,80)
+ cornflower_blue, // rgb(100,149,237)
+ cornsilk, // rgb(255,248,220)
+ crimson, // rgb(220,20,60)
+ cyan, // rgb(0,255,255)
+ dark_blue, // rgb(0,0,139)
+ dark_cyan, // rgb(0,139,139)
+ dark_golden_rod, // rgb(184,134,11)
+ dark_gray, // rgb(169,169,169)
+ dark_green, // rgb(0,100,0)
+ dark_khaki, // rgb(189,183,107)
+ dark_magenta, // rgb(139,0,139)
+ dark_olive_green, // rgb(85,107,47)
+ dark_orange, // rgb(255,140,0)
+ dark_orchid, // rgb(153,50,204)
+ dark_red, // rgb(139,0,0)
+ dark_salmon, // rgb(233,150,122)
+ dark_sea_green, // rgb(143,188,143)
+ dark_slate_blue, // rgb(72,61,139)
+ dark_slate_gray, // rgb(47,79,79)
+ dark_turquoise, // rgb(0,206,209)
+ dark_violet, // rgb(148,0,211)
+ deep_pink, // rgb(255,20,147)
+ deep_sky_blue, // rgb(0,191,255)
+ dim_gray, // rgb(105,105,105)
+ dodger_blue, // rgb(30,144,255)
+ fire_brick, // rgb(178,34,34)
+ floral_white, // rgb(255,250,240)
+ forest_green, // rgb(34,139,34)
+ fuchsia, // rgb(255,0,255)
+ gainsboro, // rgb(220,220,220)
+ ghost_white, // rgb(248,248,255)
+ gold, // rgb(255,215,0)
+ golden_rod, // rgb(218,165,32)
+ gray, // rgb(128,128,128)
+ green, // rgb(0,128,0)
+ green_yellow, // rgb(173,255,47)
+ honey_dew, // rgb(240,255,240)
+ hot_pink, // rgb(255,105,180)
+ indian_red, // rgb(205,92,92)
+ indigo, // rgb(75,0,130)
+ ivory, // rgb(255,255,240)
+ khaki, // rgb(240,230,140)
+ lavender, // rgb(230,230,250)
+ lavender_blush, // rgb(255,240,245)
+ lawn_green, // rgb(124,252,0)
+ lemon_chiffon, // rgb(255,250,205)
+ light_blue, // rgb(173,216,230)
+ light_coral, // rgb(240,128,128)
+ light_cyan, // rgb(224,255,255)
+ light_golden_rod_yellow, // rgb(250,250,210)
+ light_gray, // rgb(211,211,211)
+ light_green, // rgb(144,238,144)
+ light_pink, // rgb(255,182,193)
+ light_salmon, // rgb(255,160,122)
+ light_sea_green, // rgb(32,178,170)
+ light_sky_blue, // rgb(135,206,250)
+ light_slate_gray, // rgb(119,136,153)
+ light_steel_blue, // rgb(176,196,222)
+ light_yellow, // rgb(255,255,224)
+ lime, // rgb(0,255,0)
+ lime_green, // rgb(50,205,50)
+ linen, // rgb(250,240,230)
+ magenta, // rgb(255,0,255)
+ maroon, // rgb(128,0,0)
+ medium_aquamarine, // rgb(102,205,170)
+ medium_blue, // rgb(0,0,205)
+ medium_orchid, // rgb(186,85,211)
+ medium_purple, // rgb(147,112,219)
+ medium_sea_green, // rgb(60,179,113)
+ medium_slate_blue, // rgb(123,104,238)
+ medium_spring_green, // rgb(0,250,154)
+ medium_turquoise, // rgb(72,209,204)
+ medium_violet_red, // rgb(199,21,133)
+ midnight_blue, // rgb(25,25,112)
+ mint_cream, // rgb(245,255,250)
+ misty_rose, // rgb(255,228,225)
+ moccasin, // rgb(255,228,181)
+ navajo_white, // rgb(255,222,173)
+ navy, // rgb(0,0,128)
+ old_lace, // rgb(253,245,230)
+ olive, // rgb(128,128,0)
+ olive_drab, // rgb(107,142,35)
+ orange, // rgb(255,165,0)
+ orange_red, // rgb(255,69,0)
+ orchid, // rgb(218,112,214)
+ pale_golden_rod, // rgb(238,232,170)
+ pale_green, // rgb(152,251,152)
+ pale_turquoise, // rgb(175,238,238)
+ pale_violet_red, // rgb(219,112,147)
+ papaya_whip, // rgb(255,239,213)
+ peach_puff, // rgb(255,218,185)
+ peru, // rgb(205,133,63)
+ pink, // rgb(255,192,203)
+ plum, // rgb(221,160,221)
+ powder_blue, // rgb(176,224,230)
+ purple, // rgb(128,0,128)
+ rebecca_purple, // rgb(102,51,153)
+ red, // rgb(255,0,0)
+ rosy_brown, // rgb(188,143,143)
+ royal_blue, // rgb(65,105,225)
+ saddle_brown, // rgb(139,69,19)
+ salmon, // rgb(250,128,114)
+ sandy_brown, // rgb(244,164,96)
+ sea_green, // rgb(46,139,87)
+ sea_shell, // rgb(255,245,238)
+ sienna, // rgb(160,82,45)
+ silver, // rgb(192,192,192)
+ sky_blue, // rgb(135,206,235)
+ slate_blue, // rgb(106,90,205)
+ slate_gray, // rgb(112,128,144)
+ snow, // rgb(255,250,250)
+ spring_green, // rgb(0,255,127)
+ steel_blue, // rgb(70,130,180)
+ tan, // rgb(210,180,140)
+ teal, // rgb(0,128,128)
+ thistle, // rgb(216,191,216)
+ tomato, // rgb(255,99,71)
+ turquoise, // rgb(64,224,208)
+ violet, // rgb(238,130,238)
+ wheat, // rgb(245,222,179)
+ white, // rgb(255,255,255)
+ white_smoke, // rgb(245,245,245)
+ yellow, // rgb(255,255,0)
+ yellow_green // rgb(154,205,50)
+}; // enum class color
+namespace mgutility {
+template <> struct enum_range {
+ static constexpr auto min = 0;
+ static constexpr auto max = 150;
+};
+} // namespace mgutility
TEST_CASE("testing the enum name serialization") {
- CHECK(mgutility::enum_name(color::blue) == "blue");
- CHECK(mgutility::enum_name(color::white_smoke) == "white_smoke");
- CHECK(mgutility::enum_name(color::yellow_green) == "yellow_green");
- CHECK(mgutility::enum_name(color::steel_blue) == "steel_blue");
- CHECK(mgutility::enum_name(color::pale_turquoise) == "pale_turquoise");
- CHECK(mgutility::enum_name(color::white_smoke) == "white_smoke");
- CHECK(mgutility::enum_name(color::light_golden_rod_yellow) == "light_golden_rod_yellow");
- CHECK(mgutility::enum_name(color::dark_olive_green) == "dark_olive_green");
- CHECK(mgutility::enum_name(color::azure) == "azure");
- CHECK(mgutility::enum_name(color::ghost_white) == "ghost_white");
- CHECK(mgutility::enum_name(color::maroon) == "maroon");
- CHECK(mgutility::enum_name(color::navy) == "navy");
- CHECK(mgutility::enum_name(color::spring_green) == "spring_green");
- CHECK(mgutility::enum_name(color::rebecca_purple) == "rebecca_purple");
- CHECK(mgutility::enum_name(color::red) == "red");
- CHECK(mgutility::enum_name(color::tan) == "tan");
- CHECK(mgutility::enum_name(color::mint_cream) == "mint_cream");
- CHECK(mgutility::enum_name(color::light_green) == "light_green");
- CHECK(mgutility::enum_name(color::dodger_blue) == "dodger_blue");
- CHECK(mgutility::enum_name(color::cornflower_blue) == "cornflower_blue");
- CHECK(mgutility::enum_name<-5, 0>(color::thistle) == "");
+ CHECK(mgutility::enum_name(color::blue) == "blue");
+ CHECK(mgutility::enum_name(color::white_smoke) == "white_smoke");
+ CHECK(mgutility::enum_name(color::yellow_green) == "yellow_green");
+ CHECK(mgutility::enum_name(color::steel_blue) == "steel_blue");
+ CHECK(mgutility::enum_name(color::pale_turquoise) == "pale_turquoise");
+ CHECK(mgutility::enum_name(color::white_smoke) == "white_smoke");
+ CHECK(mgutility::enum_name(color::light_golden_rod_yellow) ==
+ "light_golden_rod_yellow");
+ CHECK(mgutility::enum_name(color::dark_olive_green) == "dark_olive_green");
+ CHECK(mgutility::enum_name(color::azure) == "azure");
+ CHECK(mgutility::enum_name(color::ghost_white) == "ghost_white");
+ CHECK(mgutility::enum_name(color::maroon) == "maroon");
+ CHECK(mgutility::enum_name(color::navy) == "navy");
+ CHECK(mgutility::enum_name(color::spring_green) == "spring_green");
+ CHECK(mgutility::enum_name(color::rebecca_purple) == "rebecca_purple");
+ CHECK(mgutility::enum_name(color::red) == "red");
+ CHECK(mgutility::enum_name(color::tan) == "tan");
+ CHECK(mgutility::enum_name(color::mint_cream) == "mint_cream");
+ CHECK(mgutility::enum_name(color::light_green) == "light_green");
+ CHECK(mgutility::enum_name(color::dodger_blue) == "dodger_blue");
+ CHECK(mgutility::enum_name(color::cornflower_blue) == "cornflower_blue");
+ CHECK(mgutility::enum_name<-5, 0>(color::thistle) == "");
}
TEST_CASE("testing the enum name deserialization") {
- CHECK(mgutility::to_enum("blue").value() == color::blue);
- CHECK(mgutility::to_enum("white_smoke").value() == color::white_smoke);
- CHECK(mgutility::to_enum("yellow_green").value() == color::yellow_green);
- CHECK(mgutility::to_enum("steel_blue").value() == color::steel_blue);
- CHECK(mgutility::to_enum( "pale_turquoise").value() == color::pale_turquoise);
- CHECK(mgutility::to_enum("white_smoke").value() == color::white_smoke);
- CHECK(mgutility::to_enum("light_golden_rod_yellow").value() == color::light_golden_rod_yellow);
- CHECK(mgutility::to_enum("dark_olive_green").value() == color::dark_olive_green);
- CHECK(mgutility::to_enum("azure").value() == color::azure);
- CHECK(mgutility::to_enum("ghost_white").value() == color::ghost_white);
- CHECK(mgutility::to_enum("maroon").value() == color::maroon);
- CHECK(mgutility::to_enum("navy").value() == color::navy);
- CHECK(mgutility::to_enum("spring_green").value() == color::spring_green);
- CHECK(mgutility::to_enum("rebecca_purple").value() == color::rebecca_purple);
- CHECK(mgutility::to_enum("red").value() == color::red);
- CHECK(mgutility::to_enum("tan").value() == color::tan);
- CHECK(mgutility::to_enum("mint_cream").value() == color::mint_cream);
- CHECK(mgutility::to_enum("light_green").value() == color::light_green);
- CHECK(mgutility::to_enum("dodger_blue").value() == color::dodger_blue);
- CHECK(mgutility::to_enum