From 0be74b835af3845023dad54b7b3145ee74c1d4d2 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 21 Nov 2019 03:49:32 +0700 Subject: [PATCH] reference impl with boost --- CMakeLists.txt | 4 +- headers/enum.hpp/enum.hpp | 107 +++++++++++++------------------ untests/enum_tests.cpp | 131 ++++++++++++++------------------------ 3 files changed, 94 insertions(+), 148 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f9033b..afa1dec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,9 +7,11 @@ endif() project(enum.hpp) +find_package(Boost REQUIRED) + add_library(${PROJECT_NAME} INTERFACE) -target_include_directories(${PROJECT_NAME} INTERFACE headers) target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17) +target_include_directories(${PROJECT_NAME} INTERFACE headers ${Boost_INCLUDE_DIRS}) if(BUILD_AS_STANDALONE) option(BUILD_WITH_UNTESTS "Build with unit tests" ON) diff --git a/headers/enum.hpp/enum.hpp b/headers/enum.hpp/enum.hpp index e48b4aa..368e189 100644 --- a/headers/enum.hpp/enum.hpp +++ b/headers/enum.hpp/enum.hpp @@ -11,6 +11,12 @@ #include #include +#include +#include +#include + +#include + namespace enum_hpp { class exception final : public std::runtime_error { @@ -20,31 +26,58 @@ namespace enum_hpp }; } -// -// ENUM_HPP_GENERATE_INTERNAL_NAMES -// +namespace enum_hpp::detail +{ + template < typename Enum > + struct ignore_assign { + Enum value; -#define ENUM_HPP_GENERATE_INTERNAL_NAMES(Fields) + constexpr explicit ignore_assign(Enum value) noexcept + : value(value) {} + + template < typename Other > + constexpr const ignore_assign& operator=(Other) const noexcept { + return *this; + } + }; + + constexpr std::string_view trim_raw_name(std::string_view raw_name) noexcept { + const auto end_index = raw_name.find_first_of(" =\r\n\t"); + return end_index == std::string_view::npos + ? raw_name + : raw_name.substr(0, end_index); + } +} // // ENUM_HPP_GENERATE_ENUM_FIELDS // -#define ENUM_HPP_GENERATE_ENUM_FIELDS(Fields) +#define ENUM_HPP_GENERATE_ENUM_FIELDS_OP(r, d, x)\ + x, + +#define ENUM_HPP_GENERATE_ENUM_FIELDS(Fields)\ + BOOST_PP_SEQ_FOR_EACH(ENUM_HPP_GENERATE_ENUM_FIELDS_OP, _, Fields) // // ENUM_HPP_GENERATE_VALUES // +#define ENUM_HPP_GENERATE_VALUES_OP(r, Enum, x)\ + ((::enum_hpp::detail::ignore_assign)Enum::x).value, + #define ENUM_HPP_GENERATE_VALUES(Enum, Fields)\ - Enum(0), + BOOST_PP_SEQ_FOR_EACH(ENUM_HPP_GENERATE_VALUES_OP, Enum, Fields) // // ENUM_HPP_GENERATE_NAMES // +#define ENUM_HPP_GENERATE_NAMES_OP(r, d, x)\ + ::enum_hpp::detail::trim_raw_name(BOOST_PP_STRINGIZE(x)), + #define ENUM_HPP_GENERATE_NAMES(Fields)\ - "", + BOOST_PP_SEQ_FOR_EACH(ENUM_HPP_GENERATE_NAMES_OP, _, Fields) // // ENUM_HPP_ENUM_CLASS @@ -56,10 +89,10 @@ namespace enum_hpp };\ struct Enum##_traits {\ private:\ - enum enum_names_for_this_score_ { ENUM_HPP_GENERATE_INTERNAL_NAMES(Fields) };\ + enum enum_names_for_this_score_ { ENUM_HPP_GENERATE_ENUM_FIELDS(Fields) };\ public:\ - static constexpr std::size_t size = ENUM_HPP_PP_SEQ_SIZE(Fields);\ - static constexpr const Enum values[] = { ENUM_HPP_GENERATE_VALUES(Enum, Fields) }; \ + static constexpr std::size_t size = BOOST_PP_SEQ_SIZE(Fields);\ + static constexpr const Enum values[] = { ENUM_HPP_GENERATE_VALUES(Enum, Fields) };\ static constexpr const std::string_view names[] = { ENUM_HPP_GENERATE_NAMES(Fields) };\ public:\ static constexpr std::string_view to_string(Enum e) noexcept {\ @@ -90,57 +123,3 @@ namespace enum_hpp return false;\ }\ }; - -// ----------------------------------------------------------------------------- -// -// ENUM_HPP_PP -// -// ----------------------------------------------------------------------------- - -// -// ENUM_HPP_PP_CAT -// - -#define ENUM_HPP_PP_CAT(x, y) ENUM_HPP_PP_CAT_I(x, y) -#define ENUM_HPP_PP_CAT_I(x, y) x ## y - -// -// ENUM_HPP_PP_APPLY -// - -#define ENUM_HPP_PP_APPLY(m, ...)\ - m(__VA_ARGS__) - -// -// ENUM_HPP_PP_SEQ_HEAD -// - -#define ENUM_HPP_PP_SEQ_HEAD(Seq) ENUM_HPP_PP_SEQ_HEAD_I(ENUM_HPP_PP_SEQ_HEAD_II Seq) -#define ENUM_HPP_PP_SEQ_HEAD_I(x) ENUM_HPP_PP_SEQ_HEAD_III(x) -#define ENUM_HPP_PP_SEQ_HEAD_II(x) x, ENUM_HPP_PP_SEQ_NOTHING -#define ENUM_HPP_PP_SEQ_HEAD_III(x, _) x - -// -// ENUM_HPP_PP_SEQ_TAIL -// - -#define ENUM_HPP_PP_SEQ_TAIL(Seq) ENUM_HPP_PP_SEQ_TAIL_I Seq -#define ENUM_HPP_PP_SEQ_TAIL_I(_) - -// -// ENUM_HPP_PP_SEQ_SIZE -// - -#define ENUM_HPP_PP_SEQ_SIZE(Seq)\ - ENUM_HPP_PP_CAT(ENUM_HPP_PP_SEQ_SIZE_, ENUM_HPP_PP_SEQ_SIZE_0 Seq) - -#define ENUM_HPP_PP_SEQ_SIZE_0(_) ENUM_HPP_PP_SEQ_SIZE_1 -#define ENUM_HPP_PP_SEQ_SIZE_1(_) ENUM_HPP_PP_SEQ_SIZE_2 -#define ENUM_HPP_PP_SEQ_SIZE_2(_) ENUM_HPP_PP_SEQ_SIZE_3 -#define ENUM_HPP_PP_SEQ_SIZE_3(_) ENUM_HPP_PP_SEQ_SIZE_4 - -#define ENUM_HPP_PP_SEQ_SIZE_ENUM_HPP_PP_SEQ_SIZE_0 0 -#define ENUM_HPP_PP_SEQ_SIZE_ENUM_HPP_PP_SEQ_SIZE_1 1 -#define ENUM_HPP_PP_SEQ_SIZE_ENUM_HPP_PP_SEQ_SIZE_2 2 -#define ENUM_HPP_PP_SEQ_SIZE_ENUM_HPP_PP_SEQ_SIZE_3 3 -#define ENUM_HPP_PP_SEQ_SIZE_ENUM_HPP_PP_SEQ_SIZE_4 4 diff --git a/untests/enum_tests.cpp b/untests/enum_tests.cpp index 628bdcc..d0664f9 100644 --- a/untests/enum_tests.cpp +++ b/untests/enum_tests.cpp @@ -41,41 +41,6 @@ namespace some_namespace }; } -TEST_CASE("enum_pp") { - SECTION("seq_head") { - REQUIRE("head"sv == ENUM_HPP_PP_SEQ_HEAD(("head"))); - REQUIRE("head"sv == ENUM_HPP_PP_SEQ_HEAD(("head")("tail"))); - REQUIRE("head"sv == ENUM_HPP_PP_SEQ_HEAD(("head")("tail1")("tail2"))); - } - - SECTION("seq_tail") { - const auto tail0 = [](){ return true; }; - REQUIRE(tail0 ENUM_HPP_PP_SEQ_TAIL(("head"))); - - const auto tail1 = [](auto t){ - REQUIRE("tail"sv == t); - return true; - }; - REQUIRE(tail1 ENUM_HPP_PP_SEQ_TAIL(("head")("tail"))); - - const auto tail2 = [](auto t1){ - REQUIRE("tail1"sv == t1); - return [](auto t2){ - REQUIRE("tail2"sv == t2); - return true; - }; - }; - REQUIRE(tail2 ENUM_HPP_PP_SEQ_TAIL(("head")("tail1")("tail2"))); - } - - SECTION("seq_size") { - STATIC_REQUIRE(ENUM_HPP_PP_SEQ_SIZE() == 0); - STATIC_REQUIRE(ENUM_HPP_PP_SEQ_SIZE((a)) == 1); - STATIC_REQUIRE(ENUM_HPP_PP_SEQ_SIZE((a)(b)) == 2); - STATIC_REQUIRE(ENUM_HPP_PP_SEQ_SIZE((a)(b)(c)) == 3); - } -} - TEST_CASE("enum") { namespace sn = some_namespace; @@ -85,90 +50,90 @@ TEST_CASE("enum") { std::underlying_type_t, unsigned>); - // REQUIRE(enum_to_underlying(sn::color::red) == 2); - // REQUIRE(enum_to_underlying(sn::color::green) == 3); - // REQUIRE(enum_to_underlying(sn::color::blue) == 6); + REQUIRE(enum_to_underlying(sn::color::red) == 2); + REQUIRE(enum_to_underlying(sn::color::green) == 3); + REQUIRE(enum_to_underlying(sn::color::blue) == 6); } { STATIC_REQUIRE(std::is_same_v< std::underlying_type_t, unsigned char>); - // REQUIRE(enum_to_underlying(sn::render::mask::none) == 0); - // REQUIRE(enum_to_underlying(sn::render::mask::color) == 1); - // REQUIRE(enum_to_underlying(sn::render::mask::alpha) == 2); - // REQUIRE(enum_to_underlying(sn::render::mask::all) == 3); + REQUIRE(enum_to_underlying(sn::render::mask::none) == 0); + REQUIRE(enum_to_underlying(sn::render::mask::color) == 1); + REQUIRE(enum_to_underlying(sn::render::mask::alpha) == 2); + REQUIRE(enum_to_underlying(sn::render::mask::all) == 3); } } SECTION("size") { { REQUIRE(sn::color_traits::size == 3); - // REQUIRE(sn::color_traits::size == std::size(sn::color_traits::names)); - // REQUIRE(sn::color_traits::size == std::size(sn::color_traits::values)); + REQUIRE(sn::color_traits::size == std::size(sn::color_traits::names)); + REQUIRE(sn::color_traits::size == std::size(sn::color_traits::values)); } { REQUIRE(sn::render::mask_traits::size == 4); - // REQUIRE(sn::render::mask_traits::size == std::size(sn::render::mask_traits::names)); - // REQUIRE(sn::render::mask_traits::size == std::size(sn::render::mask_traits::values)); + REQUIRE(sn::render::mask_traits::size == std::size(sn::render::mask_traits::names)); + REQUIRE(sn::render::mask_traits::size == std::size(sn::render::mask_traits::values)); } } SECTION("to_string") { { - // STATIC_REQUIRE(sn::color_traits::to_string(sn::color::red) == "red"); - // STATIC_REQUIRE(sn::color_traits::to_string(sn::color::green) == "green"); - // STATIC_REQUIRE(sn::color_traits::to_string(sn::color::blue) == "blue"); - // STATIC_REQUIRE(sn::color_traits::to_string(sn::color(42)) == ""); + STATIC_REQUIRE(sn::color_traits::to_string(sn::color::red) == "red"); + STATIC_REQUIRE(sn::color_traits::to_string(sn::color::green) == "green"); + STATIC_REQUIRE(sn::color_traits::to_string(sn::color::blue) == "blue"); + STATIC_REQUIRE(sn::color_traits::to_string(sn::color(42)) == ""); } { - // STATIC_REQUIRE(sn::render::mask_traits_traits::to_string(sn::render::mask::none) == "none"); - // STATIC_REQUIRE(sn::render::mask_traits_traits::to_string(sn::render::mask::color) == "color"); - // STATIC_REQUIRE(sn::render::mask_traits_traits::to_string(sn::render::mask::alpha) == "alpha"); - // STATIC_REQUIRE(sn::render::mask_traits_traits::to_string(sn::render::mask::all) == "all"); + STATIC_REQUIRE(sn::render::mask_traits::to_string(sn::render::mask::none) == "none"); + STATIC_REQUIRE(sn::render::mask_traits::to_string(sn::render::mask::color) == "color"); + STATIC_REQUIRE(sn::render::mask_traits::to_string(sn::render::mask::alpha) == "alpha"); + STATIC_REQUIRE(sn::render::mask_traits::to_string(sn::render::mask::all) == "all"); } } SECTION("from_string") { { - // REQUIRE(sn::color_traits::from_string("red") == sn::color::red); - // REQUIRE(sn::color_traits::from_string("green") == sn::color::green); - // REQUIRE(sn::color_traits::from_string("blue") == sn::color::blue); - // REQUIRE_THROWS_AS(sn::color_traits::from_string("42"), enum_hpp::exception); + REQUIRE(sn::color_traits::from_string("red") == sn::color::red); + REQUIRE(sn::color_traits::from_string("green") == sn::color::green); + REQUIRE(sn::color_traits::from_string("blue") == sn::color::blue); + REQUIRE_THROWS_AS(sn::color_traits::from_string("42"), enum_hpp::exception); } { - // REQUIRE(sn::render::mask_traits_traits::from_string("none") == sn::render::mask_traits::none); - // REQUIRE(sn::render::mask_traits_traits::from_string("color") == sn::render::mask_traits::color); - // REQUIRE(sn::render::mask_traits_traits::from_string("alpha") == sn::render::mask_traits::alpha); - // REQUIRE(sn::render::mask_traits_traits::from_string("all") == sn::render::mask_traits::all); - // REQUIRE_THROWS_AS(sn::render::mask_traits_traits::from_string("42"), enum_hpp::exception); + REQUIRE(sn::render::mask_traits::from_string("none") == sn::render::mask::none); + REQUIRE(sn::render::mask_traits::from_string("color") == sn::render::mask::color); + REQUIRE(sn::render::mask_traits::from_string("alpha") == sn::render::mask::alpha); + REQUIRE(sn::render::mask_traits::from_string("all") == sn::render::mask::all); + REQUIRE_THROWS_AS(sn::render::mask_traits::from_string("42"), enum_hpp::exception); } } SECTION("from_string_nothrow") { { - // sn::color result{42}; - // STATIC_REQUIRE(sn::color_traits::from_string_nothrow("red", result)); - // STATIC_REQUIRE(result == sn::color::red); - // STATIC_REQUIRE(sn::color_traits::from_string_nothrow("green", result)); - // STATIC_REQUIRE(result == sn::color::green); - // STATIC_REQUIRE(sn::color_traits::from_string_nothrow("blue", result)); - // STATIC_REQUIRE(result == sn::color::blue); - // STATIC_REQUIRE_FALSE(sn::color_traits::from_string_nothrow("42", result)); - // STATIC_REQUIRE(result == sn::color::blue); + sn::color result{42}; + REQUIRE(sn::color_traits::from_string_nothrow("red", result)); + REQUIRE(result == sn::color::red); + REQUIRE(sn::color_traits::from_string_nothrow("green", result)); + REQUIRE(result == sn::color::green); + REQUIRE(sn::color_traits::from_string_nothrow("blue", result)); + REQUIRE(result == sn::color::blue); + REQUIRE_FALSE(sn::color_traits::from_string_nothrow("42", result)); + REQUIRE(result == sn::color::blue); } { - // sn::render::mask result{42}; - // STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("none", result)); - // STATIC_REQUIRE(result == sn::render::mask::none); - // STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("color", result)); - // STATIC_REQUIRE(result == sn::render::mask::color); - // STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("alpha", result)); - // STATIC_REQUIRE(result == sn::render::mask::alpha); - // STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("all", result)); - // STATIC_REQUIRE(result == sn::render::mask::all); - // STATIC_REQUIRE_FALSE(sn::render::mask_traits::from_string_nothrow("42", result)); - // STATIC_REQUIRE(result == sn::render::mask::all); + sn::render::mask result{42}; + REQUIRE(sn::render::mask_traits::from_string_nothrow("none", result)); + REQUIRE(result == sn::render::mask::none); + REQUIRE(sn::render::mask_traits::from_string_nothrow("color", result)); + REQUIRE(result == sn::render::mask::color); + REQUIRE(sn::render::mask_traits::from_string_nothrow("alpha", result)); + REQUIRE(result == sn::render::mask::alpha); + REQUIRE(sn::render::mask_traits::from_string_nothrow("all", result)); + REQUIRE(result == sn::render::mask::all); + REQUIRE_FALSE(sn::render::mask_traits::from_string_nothrow("42", result)); + REQUIRE(result == sn::render::mask::all); } } }