魔术枚举C ++
仅标题C ++ 17库为枚举提供静态反射,使用任何枚举类型,而无需任何宏观或样板代码。
如果您喜欢这个项目,请考虑捐赠给有助于乌克兰战争受害者的资金之一:https://u24.gov.ua。
文档
- 参考
- 限制
- 一体化
功能和示例
-
基本的
magic_enum .hpp>
#include <iostream>enum class Color { RED = -10, BLUE = 0, GREEN = 10 };
int main() {
Color c1 = Color::RED;
std::cout << magic_enum ::enum_name(c1) << std::endl; // RED
return 0;
}\”># include < magic_enum / magic_enum .hpp > # include < iostream > enum class Color { RED = - 10 , BLUE = 0 , GREEN = 10 }; int main () { Color c1 = Color::RED; std::cout << magic_enum ::enum_name (c1) << std::endl; // RED return 0 ; }
-
枚举值
magic_enum::enum_name(color);
// color_name -> \”RED\”\”>Color color = Color::RED; auto color_name = magic_enum ::enum_name(color); // color_name -> \"RED\"
-
字符串到枚举值
magic_enum::enum_cast<Color>(color_name);
if (color.has_value()) {
// color.value() -> Color::GREEN
}// case insensitive enum_cast
auto color = magic_enum ::enum_cast<Color>(value, magic_enum ::case_insensitive);// enum_cast with BinaryPredicate
auto color = magic_enum ::enum_cast<Color>(value, [](char lhs, char rhs) { return std::tolower(lhs) == std::tolower(rhs); }// enum_cast with default
auto color_or_default = magic_enum ::enum_cast<Color>(value).value_or(Color::NONE);\”>std::string color_name{ \" GREEN \" }; auto color = magic_enum ::enum_cast<Color>(color_name); if (color.has_value()) { // color.value() -> Color::GREEN } // case insensitive enum_cast auto color = magic_enum ::enum_cast<Color>(value, magic_enum ::case_insensitive); // enum_cast with BinaryPredicate auto color = magic_enum ::enum_cast<Color>(value, []( char lhs, char rhs) { return std::tolower (lhs) == std::tolower (rhs); } // enum_cast with default auto color_or_default = magic_enum ::enum_cast<Color>(value).value_or(Color::NONE); -
整数枚举价值
magic_enum::enum_cast<Color>(color_integer);
if (color.has_value()) {
// color.value() -> Color::BLUE
}auto color_or_default = magic_enum ::enum_cast<Color>(value).value_or(Color::NONE);\”>
int color_integer = 2 ; auto color = magic_enum ::enum_cast<Color>(color_integer); if (color.has_value()) { // color.value() -> Color::BLUE } auto color_or_default = magic_enum ::enum_cast<Color>(value).value_or(Color::NONE);
-
索引访问枚举价值
magic_enum::enum_value<Color>(i);
// color -> Color::RED\”>std:: size_t i = 0 ; Color color = magic_enum ::enum_value<Color>(i); // color -> Color::RED
-
枚举值序列
magic_enum::enum_values<Color>();
// colors -> {Color::RED, Color::BLUE, Color::GREEN}
// colors[0] -> Color::RED\”>constexpr auto colors = magic_enum ::enum_values<Color>(); // colors -> {Color::RED, Color::BLUE, Color::GREEN} // colors[0] -> Color::RED
-
枚举元素数量
magic_enum::enum_count<Color>();
// color_count -> 3\”>constexpr std:: size_t color_count = magic_enum ::enum_count<Color>(); // color_count -> 3
-
对整数的枚举价值
magic_enum ::enum_underlying(color);
// color_integer -> 1\”>Color color = Color::RED; auto color_integer = magic_enum ::enum_integer(color); // or magic_enum ::enum_underlying(color); // color_integer -> 1
-
枚举名称序列
magic_enum::enum_names<Color>();
// color_names -> {\”RED\”, \”BLUE\”, \”GREEN\”}
// color_names[0] -> \”RED\”\”>constexpr auto color_names = magic_enum ::enum_names<Color>(); // color_names -> {\"RED\", \"BLUE\", \"GREEN\"} // color_names[0] -> \"RED\"
-
enum条目序列
magic_enum::enum_entries<Color>();
// color_entries -> {{Color::RED, \”RED\”}, {Color::BLUE, \”BLUE\”}, {Color::GREEN, \”GREEN\”}}
// color_entries[0].first -> Color::RED
// color_entries[0].second -> \”RED\”\”>constexpr auto color_entries = magic_enum ::enum_entries<Color>(); // color_entries -> {{Color::RED, \"RED\"}, {Color::BLUE, \"BLUE\"}, {Color::GREEN, \"GREEN\"}} // color_entries[0].first -> Color::RED // color_entries[0].second -> \"RED\"
-
多层开关/案例语句的枚举融合
magic_enum::enum_fuse(color, direction).value()) {
case magic_enum ::enum_fuse(Color::RED, Directions::Up).value(): // …
case magic_enum ::enum_fuse(Color::BLUE, Directions::Down).value(): // …
// …
}\”>switch ( magic_enum ::enum_fuse(color, direction).value()) { case magic_enum ::enum_fuse (Color::RED, Directions::Up). value (): // ... case magic_enum ::enum_fuse (Color::BLUE, Directions::Down). value (): // ... // ... }
-
枚举开关运行时值作为constexpr常数
magic_enum::enum_switch([] (auto val) {
constexpr Color c_color = val;
// …
}, color);\”>Color color = Color::RED; magic_enum ::enum_switch ([] ( auto val) { constexpr Color c_color = val; // ... }, color);
-
每个枚举作为constexpr常数的枚举
magic_enum::enum_for_each<Color>([] (auto val) {
constexpr Color c_color = val;
// …
});\”>magic_enum ::enum_for_each<Color>([] ( auto val) { constexpr Color c_color = val; // ... });
-
检查枚举是否包含
magic_enum::enum_contains(Color::GREEN); // -> true
magic_enum ::enum_contains<Color>(2); // -> true
magic_enum ::enum_contains<Color>(123); // -> false
magic_enum ::enum_contains<Color>(\”GREEN\”); // -> true
magic_enum ::enum_contains<Color>(\”fda\”); // -> false\”>magic_enum ::enum_contains (Color::GREEN); // -> true magic_enum ::enum_contains<Color>( 2 ); // -> true magic_enum ::enum_contains<Color>( 123 ); // -> false magic_enum ::enum_contains<Color>( \" GREEN \" ); // -> true magic_enum ::enum_contains<Color>( \" fda \" ); // -> false
-
序列的枚举指数
magic_enum::enum_index(Color::BLUE);
// color_index.value() -> 1
// color_index.has_value() -> true\”>constexpr auto color_index = magic_enum ::enum_index(Color::BLUE); // color_index.value() -> 1 // color_index.has_value() -> true
-
标志的功能
magic_enum::customize::enum_range<Directions> {
static constexpr bool is_flags = true;
};magic_enum ::enum_flags_name(Directions::Up | Directions::Right); // -> \”Directions::Up|Directions::Right\”
magic_enum ::enum_flags_contains(Directions::Up | Directions::Right); // -> true
magic_enum ::enum_flags_cast(3); // -> \”Directions::Left|Directions::Down\”\”>enum Directions : std:: uint64_t { Left = 1 , Down = 2 , Up = 4 , Right = 8 , }; template <> struct magic_enum ::customize::enum_range<Directions> { static constexpr bool is_flags = true ; }; magic_enum ::enum_flags_name (Directions::Up | Directions::Right); // -> \"Directions::Up|Directions::Right\" magic_enum ::enum_flags_contains (Directions::Up | Directions::Right); // -> true magic_enum ::enum_flags_cast ( 3 ); // -> \"Directions::Left|Directions::Down\"
-
枚举类型名称
magic_enum::enum_type_name<decltype(color)>();
// type_name -> \”Color\”\”>Color color = Color::RED; auto type_name = magic_enum ::enum_type_name< decltype (color)>(); // type_name -> \"Color\"
-
枚举的iostream运营商
magic_enum::iostream_operators::operator<<; // out-of-the-box ostream operators for enums.
Color color = Color::BLUE;
std::cout << color << std::endl; // \”BLUE\”\”>using magic_enum ::iostream_operators:: operator <<; // out-of-the-box ostream operators for enums. Color color = Color::BLUE; std::cout << color << std::endl; // \"BLUE\"
magic_enum::iostream_operators::operator>>; // out-of-the-box istream operators for enums.
Color color;
std::cin >> color;\”>using magic_enum ::iostream_operators:: operator >>; // out-of-the-box istream operators for enums. Color color; std::cin >> color;
-
枚举的位运算符
magic_enum::bitwise_operators; // out-of-the-box bitwise operators for enums.
// Support operators: ~, |, &, ^, |=, &=, ^=.
Flags flags = Flags::A | Flags::B & ~Flags::C;\”>enum class Flags { A = 1 << 0 , B = 1 << 1 , C = 1 << 2 , D = 1 << 3 }; using namespace magic_enum ::bitwise_operators ; // out-of-the-box bitwise operators for enums. // Support operators: ~, |, &, ^, |=, &=, ^=. Flags flags = Flags::A | Flags::B & ~Flags::C;
-
检查类型是否是未指挥的枚举。
magic_enum::is_unscoped_enum<color>::value -> true
magic_enum ::is_unscoped_enum<direction>::value -> false
magic_enum ::is_unscoped_enum<int>::value -> false// Helper variable template.
magic_enum ::is_unscoped_enum_v<color> -> true\”>enum color { red, green, blue }; enum class direction { left, right }; magic_enum ::is_unscoped_enum<color>::value -> true magic_enum ::is_unscoped_enum<direction>::value -> false magic_enum ::is_unscoped_enum< int >::value -> false // Helper variable template. magic_enum ::is_unscoped_enum_v<color> -> true
-
检查类型是否是范围的枚举。
magic_enum::is_scoped_enum<color>::value -> false
magic_enum ::is_scoped_enum<direction>::value -> true
magic_enum ::is_scoped_enum<int>::value -> false// Helper variable template.
magic_enum ::is_scoped_enum_v<direction> -> true\”>enum color { red, green, blue }; enum class direction { left, right }; magic_enum ::is_scoped_enum<color>::value -> false magic_enum ::is_scoped_enum<direction>::value -> true magic_enum ::is_scoped_enum< int >::value -> false // Helper variable template. magic_enum ::is_scoped_enum_v<direction> -> true
-
在编译时间,静态存储枚举变量此版本要轻得多,并且不仅限于enum_range限制。
magic_enum::enum_name<color>();
// color_name -> \”BLUE\”\”>constexpr Color color = Color::BLUE; constexpr auto color_name = magic_enum ::enum_name<color>(); // color_name -> \"BLUE\"
-
容器::数组阵列容器用于枚举。
magic_enum::containers::array<Color, RGB> color_rgb_array {};
color_rgb_array[Color::RED] = {255, 0, 0};
color_rgb_array[Color::GREEN] = {0, 255, 0};
color_rgb_array[Color::BLUE] = {0, 0, 255};
magic_enum ::containers::get<Color::BLUE>(color_rgb_array) // -> RGB{0, 0, 255}\”>magic_enum ::containers::array<Color, RGB> color_rgb_array {}; color_rgb_array[Color::RED] = { 255 , 0 , 0 }; color_rgb_array[Color::GREEN] = { 0 , 255 , 0 }; color_rgb_array[Color::BLUE] = { 0 , 0 , 255 }; magic_enum ::containers::get<Color::BLUE>(color_rgb_array) // -> RGB{0, 0, 255} -
容器:: bitset bitset容器用于枚举。
magic_enum::containers::bitset<Color> color_bitset_red_green {Color::RED|Color::GREEN};
bool all = color_bitset_red_green.all();
// all -> false
// Color::BLUE is missing
bool test = color_bitset_red_green.test(Color::RED);
// test -> true\”>constexpr magic_enum ::containers::bitset<Color> color_bitset_red_green {Color::RED|Color::GREEN}; bool all = color_bitset_red_green.all(); // all -> false // Color::BLUE is missing bool test = color_bitset_red_green.test(Color::RED); // test -> true
-
容器::设定的枚举容器。
magic_enum::containers::set<Color>();
bool empty = color_set.empty();
// empty -> true
color_set.insert(Color::GREEN);
color_set.insert(Color::BLUE);
color_set.insert(Color::RED);
std::size_t size = color_set.size();
// size -> 3\”>auto color_set = magic_enum ::containers::set<Color>(); bool empty = color_set.empty(); // empty -> true color_set.insert(Color::GREEN); color_set.insert(Color::BLUE); color_set.insert(Color::RED); std:: size_t size = color_set.size(); // size -> 3
-
改进了无UB“ Sfinae-Finae-Frylyly”的基础type。
magic_enum::underlying_type<color>::type -> int
// Helper types.
magic_enum ::underlying_type_t<Direction> -> int\”>magic_enum ::underlying_type<color>::type -> int // Helper types. magic_enum :: underlying_type_t <Direction> -> int
评论
-
magic_enum并不假装是用于枚举的反射的银色子弹,它最初是为小枚举而设计的。
-
使用前,请阅读功能的局限性。
一体化
-
您应该添加所需的文件magic_enum .hpp,以及可选的其他标题,包括DIR或Release Archive。另外,您可以使用CMAKE构建库。
-
如果您在项目上使用VCPKG来用于外部依赖项,则可以使用魔术包装包。
-
如果您使用柯南来管理依赖项,则仅在柯南的要求中添加magic_enum /xyz,xyz是您要使用的发行版本。
-
如果您使用build2来构建和管理依赖关系,则添加依赖性: magic_enum ^xyz到清单文件中xyz是您要使用的发行版本。然后,您可以使用magic_enum %lib { magic_enum }导入目标。
-
另外,您可以使用基于CMAKE的Fetch_Content模块之类的CPM。
magic_enum
GITHUB_REPOSITORY Neargye/ magic_enum
GIT_TAG vx.y.z # Where `x.y.z` is the release version you want to use.
)\”>CPMAddPackage ( NAME magic_enum GITHUB_REPOSITORY Neargye/ magic_enum GIT_TAG vx.y.z # Where `x.y.z` is the release version you want to use. )
-
也支持Bazel,只需添加到您的工作区文件:
magic_enum\”,
strip_prefix = \” magic_enum -<commit>\”,
urls = [\”https://*git*h*ub.com/Neargye/magic_enum/archive/<commit>.zip\”],
)\”>http_archive( name = \" magic_enum \", strip_prefix = \" magic_enum -<commit>\", urls = [\"https://*git*h*ub.com/Neargye/magic_enum/archive/<commit>.zip\"], )要在存储库中使用Bazel,可以做:
bazel build //... bazel test //... bazel run //example
(请注意,您必须使用支持的编译器或使用导出CC = <编译器>指定它。)
-
如果您使用的是ROS,则可以通过将<dived> magic_enum </dived>添加到poffage.xml中,并将此软件包包含在工作区中。在您的cmakelists.txt中添加以下内容:
magic_enum CONFIG REQUIRED)
…
target_link_libraries(your_executable magic_enum :: magic_enum )\”>find_package ( magic_enum CONFIG REQUIRED ) ... target_link_libraries ( your_executable magic_enum :: magic_enum )
编译器兼容性
- clang/llvm> = 5
- MSVC ++> = 14.11 / Visual Studio> = 2017
- Xcode> = 10
- GCC> = 9
- mingw> = 9
