From d24d38ea50f9b13a216c6473d933cc9f4d12880e Mon Sep 17 00:00:00 2001 From: neargye Date: Mon, 8 Apr 2019 18:29:03 +0500 Subject: [PATCH] add is_unscoped_enum/is_scoped_enum --- README.md | 28 ++++++++++++++++++++++++++++ include/magic_enum.hpp | 32 ++++++++++++++++++++++++++++++-- test/test.cpp | 12 ++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3a20c06..980e32b 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ Header-only C++17 library provides static reflection on enums, work with any enu * `enum_count` returns number of enum values. * `enum_name` obtains string name from enum value. * `enum_names` obtains string enum name sequence. +* `is_unscoped_enum` checks whether type is an Unscoped enumeration. +* `is_scoped_enum` checks whether type is an Scoped enumeration. ## Features @@ -137,6 +139,32 @@ enum Color { RED = 2, BLUE = 4, GREEN = 8 }; std::cout << color << std::endl; // "BLUE" ``` +* Checks whether type is an Unscoped enumeration. + ```cpp + enum сolor { red, green, blue }; + enum class direction { left, right }; + + magic_enum::is_unscoped_enum::value -> true + magic_enum::is_unscoped_enum::value -> false + magic_enum::is_unscoped_enum::value -> false + + // Helper variable template. + magic_enum::is_unscoped_enum_v -> true + ``` + +* Checks whether type is an Scoped enumeration. + ```cpp + enum сolor { red, green, blue }; + enum class direction { left, right }; + + magic_enum::is_scoped_enum::value -> false + magic_enum::is_scoped_enum::value -> true + magic_enum::is_scoped_enum::value -> false + + // Helper variable template. + magic_enum::is_scoped_enum_v -> true + ``` + ## Remarks * `magic_enum::enum_cast` returns `std::optional`, using `has_value()` to check contains enum value and `value()` to get the enum value. diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 969fe9f..a89502b 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -180,11 +180,39 @@ template return std::nullopt; // Invalid value or out of range. } -template -using enable_if_enum_t = typename std::enable_if>>::type; +template +using enable_if_enum_t = typename std::enable_if>>::type; + +template> +struct is_scoped_enum_impl : std::false_type {}; + +template +struct is_scoped_enum_impl : std::bool_constant>> {}; + +template> +struct is_unscoped_enum_impl : std::false_type {}; + +template +struct is_unscoped_enum_impl : std::bool_constant>> {}; } // namespace magic_enum::detail +// Checks whether T is an Unscoped enumeration type. Provides the member constant value which is equal to true, if T is an Unscoped enumeration type. Otherwise, value is equal to false. +// https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration +template +struct is_unscoped_enum : detail::is_unscoped_enum_impl {}; + +template +inline constexpr bool is_unscoped_enum_v = is_unscoped_enum::value; + +// Checks whether T is an Scoped enumeration type. Provides the member constant value which is equal to true, if T is an Scoped enumeration type. Otherwise, value is equal to false. +// https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations +template +struct is_scoped_enum : detail::is_scoped_enum_impl {}; + +template +inline constexpr bool is_scoped_enum_v = is_scoped_enum::value; + // Obtains enum value from enum string name. template > [[nodiscard]] constexpr std::optional enum_cast(std::string_view value) noexcept { diff --git a/test/test.cpp b/test/test.cpp index 67588d6..fc5a5a1 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -233,3 +233,15 @@ TEST_CASE("operator<<") { test_ostream(number::three, "three"); test_ostream((number)0, ""); } + +TEST_CASE("type_traits") { + REQUIRE_FALSE(magic_enum::is_unscoped_enum_v); + REQUIRE_FALSE(magic_enum::is_unscoped_enum_v); + REQUIRE(magic_enum::is_unscoped_enum_v); + REQUIRE(magic_enum::is_unscoped_enum_v); + + REQUIRE(magic_enum::is_scoped_enum_v); + REQUIRE(magic_enum::is_scoped_enum_v); + REQUIRE_FALSE(magic_enum::is_scoped_enum_v); + REQUIRE_FALSE(magic_enum::is_scoped_enum_v); +}