mirror of
https://github.com/BlackMATov/enum.hpp.git
synced 2025-12-15 11:53:50 +07:00
basic structure and tests
This commit is contained in:
@@ -6,6 +6,141 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
namespace enum_hpp
|
namespace enum_hpp
|
||||||
{
|
{
|
||||||
|
class exception final : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
explicit exception(const char* what)
|
||||||
|
: std::runtime_error(what) {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// ENUM_HPP_GENERATE_INTERNAL_NAMES
|
||||||
|
//
|
||||||
|
|
||||||
|
#define ENUM_HPP_GENERATE_INTERNAL_NAMES(Fields)
|
||||||
|
|
||||||
|
//
|
||||||
|
// ENUM_HPP_GENERATE_ENUM_FIELDS
|
||||||
|
//
|
||||||
|
|
||||||
|
#define ENUM_HPP_GENERATE_ENUM_FIELDS(Fields)
|
||||||
|
|
||||||
|
//
|
||||||
|
// ENUM_HPP_GENERATE_VALUES
|
||||||
|
//
|
||||||
|
|
||||||
|
#define ENUM_HPP_GENERATE_VALUES(Enum, Fields)\
|
||||||
|
Enum(0),
|
||||||
|
|
||||||
|
//
|
||||||
|
// ENUM_HPP_GENERATE_NAMES
|
||||||
|
//
|
||||||
|
|
||||||
|
#define ENUM_HPP_GENERATE_NAMES(Fields)\
|
||||||
|
"",
|
||||||
|
|
||||||
|
//
|
||||||
|
// ENUM_HPP_ENUM_CLASS
|
||||||
|
//
|
||||||
|
|
||||||
|
#define ENUM_HPP_ENUM_CLASS(Enum, Type, Fields)\
|
||||||
|
enum class Enum : Type {\
|
||||||
|
ENUM_HPP_GENERATE_ENUM_FIELDS(Fields)\
|
||||||
|
};\
|
||||||
|
struct Enum##_traits {\
|
||||||
|
private:\
|
||||||
|
enum enum_names_for_this_score_ { ENUM_HPP_GENERATE_INTERNAL_NAMES(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 const std::string_view names[] = { ENUM_HPP_GENERATE_NAMES(Fields) };\
|
||||||
|
public:\
|
||||||
|
static constexpr std::string_view to_string(Enum e) noexcept {\
|
||||||
|
for ( std::size_t i = 0; i < size; ++i) {\
|
||||||
|
if ( e == values[i] ) {\
|
||||||
|
return names[i];\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
return std::string_view();\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
static Enum from_string(std::string_view name){\
|
||||||
|
for ( std::size_t i = 0; i < size; ++i) {\
|
||||||
|
if ( name == names[i] ) {\
|
||||||
|
return values[i];\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
throw ::enum_hpp::exception(#Enum "_traits::from_string(): invalid argument");\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
static constexpr bool from_string_nothrow(std::string_view name, Enum& result) noexcept {\
|
||||||
|
for ( std::size_t i = 0; i < size; ++i) {\
|
||||||
|
if ( name == names[i] ) {\
|
||||||
|
result = values[i];\
|
||||||
|
return true;\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
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
|
||||||
|
|||||||
@@ -9,5 +9,166 @@
|
|||||||
|
|
||||||
#include <enum.hpp/enum.hpp>
|
#include <enum.hpp/enum.hpp>
|
||||||
|
|
||||||
TEST_CASE("enum") {
|
#include <iterator>
|
||||||
|
#include <string_view>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template < typename Enum >
|
||||||
|
constexpr std::underlying_type_t<Enum> enum_to_underlying(Enum e) noexcept {
|
||||||
|
return static_cast<std::underlying_type_t<Enum>>(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace some_namespace
|
||||||
|
{
|
||||||
|
ENUM_HPP_ENUM_CLASS(color, unsigned,
|
||||||
|
(red = 2)
|
||||||
|
(green)
|
||||||
|
(blue = red + 4)
|
||||||
|
)
|
||||||
|
|
||||||
|
struct render {
|
||||||
|
ENUM_HPP_ENUM_CLASS(mask, unsigned char,
|
||||||
|
(none)
|
||||||
|
(color = 1 << 0)
|
||||||
|
(alpha = 1 << 1)
|
||||||
|
(all = color | alpha)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
SECTION("declaration") {
|
||||||
|
{
|
||||||
|
STATIC_REQUIRE(std::is_same_v<
|
||||||
|
std::underlying_type_t<sn::color>,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
STATIC_REQUIRE(std::is_same_v<
|
||||||
|
std::underlying_type_t<sn::render::mask>,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user