reference impl with boost

This commit is contained in:
2019-11-21 03:49:32 +07:00
parent 2b18d09dc8
commit 0be74b835a
3 changed files with 94 additions and 148 deletions

View File

@@ -7,9 +7,11 @@ endif()
project(enum.hpp) project(enum.hpp)
find_package(Boost REQUIRED)
add_library(${PROJECT_NAME} INTERFACE) add_library(${PROJECT_NAME} INTERFACE)
target_include_directories(${PROJECT_NAME} INTERFACE headers)
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17) target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17)
target_include_directories(${PROJECT_NAME} INTERFACE headers ${Boost_INCLUDE_DIRS})
if(BUILD_AS_STANDALONE) if(BUILD_AS_STANDALONE)
option(BUILD_WITH_UNTESTS "Build with unit tests" ON) option(BUILD_WITH_UNTESTS "Build with unit tests" ON)

View File

@@ -11,6 +11,12 @@
#include <stdexcept> #include <stdexcept>
#include <string_view> #include <string_view>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/stringize.hpp>
namespace enum_hpp namespace enum_hpp
{ {
class exception final : public std::runtime_error { class exception final : public std::runtime_error {
@@ -20,31 +26,58 @@ namespace enum_hpp
}; };
} }
// namespace enum_hpp::detail
// ENUM_HPP_GENERATE_INTERNAL_NAMES {
// 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 // 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 // ENUM_HPP_GENERATE_VALUES
// //
#define ENUM_HPP_GENERATE_VALUES_OP(r, Enum, x)\
((::enum_hpp::detail::ignore_assign<Enum>)Enum::x).value,
#define ENUM_HPP_GENERATE_VALUES(Enum, Fields)\ #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 // 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)\ #define ENUM_HPP_GENERATE_NAMES(Fields)\
"", BOOST_PP_SEQ_FOR_EACH(ENUM_HPP_GENERATE_NAMES_OP, _, Fields)
// //
// ENUM_HPP_ENUM_CLASS // ENUM_HPP_ENUM_CLASS
@@ -56,10 +89,10 @@ namespace enum_hpp
};\ };\
struct Enum##_traits {\ struct Enum##_traits {\
private:\ 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:\ public:\
static constexpr std::size_t size = ENUM_HPP_PP_SEQ_SIZE(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 Enum values[] = { ENUM_HPP_GENERATE_VALUES(Enum, Fields) };\
static constexpr const std::string_view names[] = { ENUM_HPP_GENERATE_NAMES(Fields) };\ static constexpr const std::string_view names[] = { ENUM_HPP_GENERATE_NAMES(Fields) };\
public:\ public:\
static constexpr std::string_view to_string(Enum e) noexcept {\ static constexpr std::string_view to_string(Enum e) noexcept {\
@@ -90,57 +123,3 @@ namespace enum_hpp
return false;\ 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

View File

@@ -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") { TEST_CASE("enum") {
namespace sn = some_namespace; namespace sn = some_namespace;
@@ -85,90 +50,90 @@ TEST_CASE("enum") {
std::underlying_type_t<sn::color>, std::underlying_type_t<sn::color>,
unsigned>); unsigned>);
// REQUIRE(enum_to_underlying(sn::color::red) == 2); REQUIRE(enum_to_underlying(sn::color::red) == 2);
// REQUIRE(enum_to_underlying(sn::color::green) == 3); REQUIRE(enum_to_underlying(sn::color::green) == 3);
// REQUIRE(enum_to_underlying(sn::color::blue) == 6); REQUIRE(enum_to_underlying(sn::color::blue) == 6);
} }
{ {
STATIC_REQUIRE(std::is_same_v< STATIC_REQUIRE(std::is_same_v<
std::underlying_type_t<sn::render::mask>, std::underlying_type_t<sn::render::mask>,
unsigned char>); unsigned char>);
// REQUIRE(enum_to_underlying(sn::render::mask::none) == 0); 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::color) == 1);
// REQUIRE(enum_to_underlying(sn::render::mask::alpha) == 2); 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::all) == 3);
} }
} }
SECTION("size") { SECTION("size") {
{ {
REQUIRE(sn::color_traits::size == 3); 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::names));
// REQUIRE(sn::color_traits::size == std::size(sn::color_traits::values)); REQUIRE(sn::color_traits::size == std::size(sn::color_traits::values));
} }
{ {
REQUIRE(sn::render::mask_traits::size == 4); 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::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::values));
} }
} }
SECTION("to_string") { SECTION("to_string") {
{ {
// STATIC_REQUIRE(sn::color_traits::to_string(sn::color::red) == "red"); 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::green) == "green");
// STATIC_REQUIRE(sn::color_traits::to_string(sn::color::blue) == "blue"); 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(42)) == "");
} }
{ {
// STATIC_REQUIRE(sn::render::mask_traits_traits::to_string(sn::render::mask::none) == "none"); STATIC_REQUIRE(sn::render::mask_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::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::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::all) == "all");
} }
} }
SECTION("from_string") { SECTION("from_string") {
{ {
// REQUIRE(sn::color_traits::from_string("red") == sn::color::red); 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("green") == sn::color::green);
// REQUIRE(sn::color_traits::from_string("blue") == sn::color::blue); REQUIRE(sn::color_traits::from_string("blue") == sn::color::blue);
// REQUIRE_THROWS_AS(sn::color_traits::from_string("42"), enum_hpp::exception); 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::from_string("none") == sn::render::mask::none);
// REQUIRE(sn::render::mask_traits_traits::from_string("color") == sn::render::mask_traits::color); REQUIRE(sn::render::mask_traits::from_string("color") == sn::render::mask::color);
// REQUIRE(sn::render::mask_traits_traits::from_string("alpha") == sn::render::mask_traits::alpha); REQUIRE(sn::render::mask_traits::from_string("alpha") == sn::render::mask::alpha);
// REQUIRE(sn::render::mask_traits_traits::from_string("all") == sn::render::mask_traits::all); REQUIRE(sn::render::mask_traits::from_string("all") == sn::render::mask::all);
// REQUIRE_THROWS_AS(sn::render::mask_traits_traits::from_string("42"), enum_hpp::exception); REQUIRE_THROWS_AS(sn::render::mask_traits::from_string("42"), enum_hpp::exception);
} }
} }
SECTION("from_string_nothrow") { SECTION("from_string_nothrow") {
{ {
// sn::color result{42}; sn::color result{42};
// STATIC_REQUIRE(sn::color_traits::from_string_nothrow("red", result)); REQUIRE(sn::color_traits::from_string_nothrow("red", result));
// STATIC_REQUIRE(result == sn::color::red); REQUIRE(result == sn::color::red);
// STATIC_REQUIRE(sn::color_traits::from_string_nothrow("green", result)); REQUIRE(sn::color_traits::from_string_nothrow("green", result));
// STATIC_REQUIRE(result == sn::color::green); REQUIRE(result == sn::color::green);
// STATIC_REQUIRE(sn::color_traits::from_string_nothrow("blue", result)); REQUIRE(sn::color_traits::from_string_nothrow("blue", result));
// STATIC_REQUIRE(result == sn::color::blue); REQUIRE(result == sn::color::blue);
// STATIC_REQUIRE_FALSE(sn::color_traits::from_string_nothrow("42", result)); REQUIRE_FALSE(sn::color_traits::from_string_nothrow("42", result));
// STATIC_REQUIRE(result == sn::color::blue); REQUIRE(result == sn::color::blue);
} }
{ {
// sn::render::mask result{42}; sn::render::mask result{42};
// STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("none", result)); REQUIRE(sn::render::mask_traits::from_string_nothrow("none", result));
// STATIC_REQUIRE(result == sn::render::mask::none); REQUIRE(result == sn::render::mask::none);
// STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("color", result)); REQUIRE(sn::render::mask_traits::from_string_nothrow("color", result));
// STATIC_REQUIRE(result == sn::render::mask::color); REQUIRE(result == sn::render::mask::color);
// STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("alpha", result)); REQUIRE(sn::render::mask_traits::from_string_nothrow("alpha", result));
// STATIC_REQUIRE(result == sn::render::mask::alpha); REQUIRE(result == sn::render::mask::alpha);
// STATIC_REQUIRE(sn::render::mask_traits::from_string_nothrow("all", result)); REQUIRE(sn::render::mask_traits::from_string_nothrow("all", result));
// STATIC_REQUIRE(result == sn::render::mask::all); REQUIRE(result == sn::render::mask::all);
// STATIC_REQUIRE_FALSE(sn::render::mask_traits::from_string_nothrow("42", result)); REQUIRE_FALSE(sn::render::mask_traits::from_string_nothrow("42", result));
// STATIC_REQUIRE(result == sn::render::mask::all); REQUIRE(result == sn::render::mask::all);
} }
} }
} }