diff --git a/README.md b/README.md index c0d4840..0eb275d 100644 --- a/README.md +++ b/README.md @@ -24,46 +24,13 @@ Header-only C++17 library provides static reflection for enums, work with any enum type without any macro or boilerplate code. -* `enum_cast` obtains enum value from string or integer. -* `enum_value` returns enum value at specified index. -* `enum_values` obtains enum value sequence. -* `enum_count` returns number of enum values. -* `enum_integer` obtains integer value from enum value. -* `enum_name` returns name from enum value. -* `enum_names` obtains string enum name sequence. -* `enum_entries` obtains pair (value enum, string enum name) sequence. -* `enum_index` obtains index in enum value sequence from enum value. -* `enum_contains` checks whether enum contains enumerator with such value. -* `enum_type_name` returns name of enum type. -* `enum_fuse` allows multidimensional switch/cases. -* `enum_switch` allows runtime enum value transformation to constexpr context. -* `enum_for_each` calls a function with all enum constexpr value. -* `is_unscoped_enum` checks whether type is an [Unscoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Unscoped_enumeration). -* `is_scoped_enum` checks whether type is an [Scoped enumeration](https://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations). -* `underlying_type` improved UB-free "SFINAE-friendly" [underlying_type](https://en.cppreference.com/w/cpp/types/underlying_type). -* `ostream_operators` ostream operators for enums. -* `bitwise_operators` bitwise operators for enums. -* `containers::array` array container for enums. -* `containers::bitset` bitset container for enums. -* `containers::set` set container for enums. - ## Documentation * [Reference](doc/reference.md) * [Limitations](doc/limitations.md) * [Integration](#Integration) -## Features - -* C++17 -* Header-only -* Dependency-free -* Compile-time -* Enum to string -* String to enum -* Iterating over enum - -## [Examples](example/example.cpp) +## [Examples](example/) * Enum value to string @@ -124,8 +91,8 @@ Header-only C++17 library provides static reflection for enums, work with any en ```cpp Color color = Color::RED; - auto color_integer = magic_enum::enum_integer(color); - // color -> 1 + auto color_integer = magic_enum::enum_integer(color); // or magic_enum::enum_underlying(color); + // color_integer -> 1 ``` * Enum names sequence @@ -154,7 +121,7 @@ Header-only C++17 library provides static reflection for enums, work with any en // ... } ``` - + * Enum switch runtime value as constexpr constant ```cpp Color color = Color::RED; @@ -172,9 +139,58 @@ Header-only C++17 library provides static reflection for enums, work with any en }); ``` -* Ostream operator for enum +* Check if enum contains ```cpp + magic_enum::enum_contains(Color::GREEN); // -> true + magic_enum::enum_contains(2); // -> true + magic_enum::enum_contains(123); // -> false + magic_enum::enum_contains("GREEN"); // -> true + magic_enum::enum_contains("fda"); // -> false + ``` + +* Enum index in sequence + + ```cpp + constexpr auto color_index = magic_enum::enum_index(Color::BLUE); + // color_index.value() -> 1 + // color_index.has_value() -> true + ``` + +* Functions for flags + + ```cpp + enum Directions : std::uint64_t { + Left = 1, + Down = 2, + Up = 4, + Right = 8, + }; + template <> + struct magic_enum::customize::enum_range { + static constexpr bool is_flags = true; + }; + + magic_enum::enum_flags_name(Directions::Up | Directions::Right); // directions_name -> "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 type name + + ```cpp + Color color = Color::RED; + auto type_name = magic_enum::enum_type_name(); + // type_name -> "Color" + ``` + +* IOstream operator for enum + + ```cpp + using namespace magic_enum::ostream_operators; // out-of-the-box ostream operators for enums. + Color color = Color::BLUE; + std::cout << color << std::endl; // "BLUE" + using namespace magic_enum::ostream_operators; // out-of-the-box ostream operators for enums. Color color = Color::BLUE; std::cout << color << std::endl; // "BLUE" @@ -260,6 +276,14 @@ Header-only C++17 library provides static reflection for enums, work with any en // size -> 3 ``` +* Improved UB-free "SFINAE-friendly" [underlying_type](https://en.cppreference.com/w/cpp/types/underlying_type). + + ```cpp + magic_enum::underlying_type::type -> int + + // Helper types. + magic_enum::underlying_type_t -> int + ``` ## Remarks * `magic_enum` does not pretend to be a silver bullet for reflection for enums, it was originally designed for small enum. @@ -315,7 +339,7 @@ Header-only C++17 library provides static reflection for enums, work with any en ## Compiler compatibility -* Clang/LLVM >= 6 +* Clang/LLVM >= 5 * MSVC++ >= 14.11 / Visual Studio >= 2017 * Xcode >= 10 * GCC >= 9 diff --git a/doc/reference.md b/doc/reference.md index 4c2da45..04f7f4f 100644 --- a/doc/reference.md +++ b/doc/reference.md @@ -14,7 +14,7 @@ * [`enum_fuse` returns a bijective mix of enum values.](#enum_fuse) * [`enum_switch` allows runtime enum value transformation to constexpr context.](#enum_switch) * [`enum_for_each` calls a function with all enum constexpr value.](#enum_for_each) -* [`enum_flags` API from enum-flags.](#enum_flags) +* [`enum_flags_*` functions for flags.](#enum_flags) * [`is_unscoped_enum` checks whether type is an Unscoped enumeration.](#is_unscoped_enum) * [`is_scoped_enum` checks whether type is an Scoped enumeration.](#is_scoped_enum) * [`underlying_type` improved UB-free "SFINAE-friendly" underlying_type.](#underlying_type) @@ -34,7 +34,7 @@ * To add custom enum or type names see the [example](../example/example_custom_name.cpp). -* To change the type of strings or ortional, use special macros: +* To change the type of strings or optional, use special macros: ```cpp #include @@ -292,7 +292,7 @@ template constexpr bool enum_contains(string_view value) noexcept; template -constexpr optional enum_contains(string_view value, BinaryPredicate p) noexcept(is_nothrow_invocable_v); +constexpr bool enum_contains(string_view value, BinaryPredicate p) noexcept(is_nothrow_invocable_v); ``` * Checks whether enum contains enumerator with such value. @@ -330,7 +330,7 @@ constexpr string_view enum_type_name() noexcept; ```cpp template -[[nodiscard]] constexpr optional enum_fuse(Es... values) noexcept; +constexpr optional enum_fuse(Es... values) noexcept; ``` * You should add the required file ``. @@ -387,9 +387,10 @@ constexpr auto enum_for_each(Lambda&& lambda); * Examples ```cpp - magic_enum::enum_for_each([] (auto val) { - constexpr Color c_color = val; - // ... + underlying_type_t sum{}; + enum_for_each([&sum](auto val) { + constexpr underlying_type_t v = enum_integer(val()); + sum += v; }); ``` @@ -418,16 +419,27 @@ template constexpr bool enum_flags_contains(string_view value) noexcept; template -constexpr optional enum_flags_contains(string_view value, BinaryPredicate p) noexcept(is_nothrow_invocable_v); +constexpr bool enum_flags_contains(string_view value, BinaryPredicate p) noexcept(is_nothrow_invocable_v); ``` * Examples ```cpp - auto directions_name = magic_enum::enum_flags_name(Directions::Up | Directions::Right); - // directions_name -> "Directions::Up|Directions::Right" - ``` + enum Directions : std::uint64_t { + Left = 1, + Down = 2, + Up = 4, + Right = 8, + }; + template <> + struct magic_enum::customize::enum_range { + static constexpr bool is_flags = true; + }; + magic_enum::enum_flags_name(Directions::Up | Directions::Right); // directions_name -> "Directions::Up|Directions::Right" + magic_enum::enum_flags_contains(Directions::Up | Directions::Right); // -> true + magic_enum::enum_flags_cast(3); // -> "Directions::Left|Directions::Down" + ``` ## `is_unscoped_enum` @@ -584,7 +596,7 @@ constexpr E& operator^=(E& lhs, E rhs) noexcept; ## `containers::array` ```cpp -template> +template > struct array { constexpr reference at(E pos); @@ -637,7 +649,7 @@ struct array { constexpr size_type max_size() const noexcept; - constexpr void fill( const V& value ); + constexpr void fill(const V& value); constexpr void swap(array& other) noexcept(std::is_nothrow_swappable_v); @@ -674,7 +686,7 @@ struct array { ## `containers::bitset` ```cpp -template> +template > class bitset { constexpr explicit bitset(detail::raw_access_t = raw_access) noexcept; @@ -685,28 +697,27 @@ class bitset { string_view sv, string_view::size_type pos = 0, string_view::size_type n = string_view::npos, - char zero = '0', - char one = '1'); + char_type zero = '0', + char_type one = '1'); constexpr explicit bitset(detail::raw_access_t, - const char* str, + const char_type* str, std::size_t n = ~std::size_t{}, - char zero = '0', - char one = '1'); + char_type zero = '0', + char_type one = '1'); constexpr bitset(std::initializer_list starters); - template - constexpr explicit bitset(std::enable_if_t, E> starter); + constexpr explicit bitset(E starter); - template> + template > constexpr explicit bitset(string_view sv, Cmp&& cmp = {}, - char sep = '|'); + char_type sep = '|'); - friend constexpr bool operator==( const bitset& lhs, const bitset& rhs ) noexcept; + friend constexpr bool operator==(const bitset& lhs, const bitset& rhs) noexcept; - friend constexpr bool operator!=( const bitset& lhs, const bitset& rhs ) noexcept; + friend constexpr bool operator!=(const bitset& lhs, const bitset& rhs) noexcept; constexpr bool operator[](E pos) const noexcept; @@ -750,14 +761,13 @@ class bitset { friend constexpr bitset operator^(const bitset& lhs, const bitset& rhs) noexcept; - template - constexpr explicit operator std::enable_if_t, E>() const; + constexpr explicit operator E() const; - string to_string(char sep = '|') const; + string to_string(char_type sep = '|') const; string to_string(detail::raw_access_t, - char zero = '0', - char one = '1') const; + char_type zero = '0', + char_type one = '1') const; constexpr unsigned long long to_ullong(detail::raw_access_t raw) const; @@ -793,18 +803,17 @@ class bitset { ## `containers::set` ```cpp -template> +template > class set { constexpr set() noexcept = default; - template + template constexpr set(InputIt first, InputIt last); constexpr set(std::initializer_list ilist); - template - constexpr explicit set(std::enable_if_t, E> starter); + constexpr explicit set(E starter); constexpr set(const set&) noexcept = default; @@ -848,15 +857,15 @@ class set { constexpr iterator insert(const_iterator hint, value_type&& value) noexcept; - template< class InputIt > + template constexpr void insert(InputIt first, InputIt last) noexcept; constexpr void insert(std::initializer_list ilist) noexcept; - template - constexpr std::pair emplace(Args&&... args) noexcept; + template + constexpr std::pair emplace(Args&&... args) noexcept; - template + template constexpr iterator emplace_hint(const_iterator, Args&&... args) noexcept; constexpr iterator erase(const_iterator pos) noexcept; @@ -865,39 +874,39 @@ class set { constexpr size_type erase(const key_type& key) noexcept; - template + template constexpr std::enable_if_t, size_type> erase(K&& x) noexcept; void swap(set& other) noexcept; constexpr size_type count(const key_type& key) const noexcept; - template + template constexpr std::enable_if_t, size_type> count(const K& x) const; constexpr const_iterator find(const key_type & key) const noexcept; - template + template constexpr std::enable_if_t, const_iterator> find(const K& x) const; constexpr bool contains(const key_type& key) const noexcept; - template + template constexpr std::enable_if_t, bool> contains(const K& x) const noexcept; constexpr std::pair equal_range(const key_type& key) const noexcept; - template + template constexpr std::enable_if_t, std::pair> equal_range(const K& x) const noexcept; constexpr const_iterator lower_bound(const key_type& key) const noexcept; - template + template constexpr std::enable_if_t, const_iterator> lower_bound(const K& x) const noexcept; constexpr const_iterator upper_bound(const key_type& key) const noexcept; - template + template constexpr std::enable_if_t, const_iterator> upper_bound(const K& x) const noexcept; constexpr key_compare key_comp() const; @@ -916,7 +925,7 @@ class set { constexpr friend bool operator>=(const set& lhs, const set& rhs) noexcept; - template + template size_type erase_if(Pred pred); } ```