diff --git a/doc/reference.md b/doc/reference.md index 1dc30ec..4c2da45 100644 --- a/doc/reference.md +++ b/doc/reference.md @@ -19,6 +19,7 @@ * [`is_scoped_enum` checks whether type is an Scoped enumeration.](#is_scoped_enum) * [`underlying_type` improved UB-free "SFINAE-friendly" underlying_type.](#underlying_type) * [`ostream_operators` ostream operators for enums.](#ostream_operators) +* [`istream_operators` istream operators for enums.](#istream_operators) * [`bitwise_operators` bitwise operators for enums.](#bitwise_operators) * [`containers::array` array container for enums.](#containersarray) * [`containers::bitset` bitset container for enums.](#containersbitset) @@ -511,9 +512,10 @@ basic_ostream& operator<<(basic_ostream& os, E value template basic_ostream& operator<<(basic_ostream& os, optional value); - ``` +* You should add the required file ``. + * Out-of-the-box ostream operators for all enums. * Examples @@ -524,6 +526,25 @@ basic_ostream& operator<<(basic_ostream& os, optiona std::cout << color << std::endl; // "BLUE" ``` +## `istream_operators` + +```cpp +template +basic_istream& operator>>(basic_istream& is, E& value); +``` + +* You should add the required file ``. + +* Out-of-the-box istream operators for all enums. + +* Examples + + ```cpp + using namespace magic_enum::istream_operators; // out-of-the-box istream operators for enums. + Color color; + std::cin >> color; + ``` + ## `bitwise_operators` ```cpp diff --git a/example/enum_flag_example.cpp b/example/enum_flag_example.cpp index aeee293..f6e5520 100644 --- a/example/enum_flag_example.cpp +++ b/example/enum_flag_example.cpp @@ -24,13 +24,14 @@ #include #include +#include enum class AnimalFlags : std::uint64_t { HasClaws = 1 << 10, CanFly = 1 << 20, EatsFish = 1 << 30, Endangered = std::uint64_t{1} << 40 }; -// Add specialization `is_flags` to force define that enum are flags. -//template <> -//struct magic_enum::customize::enum_range { -// static constexpr bool is_flags = true; -//}; +// Add specialization `is_flags` to define that enum are flags. +template <> +struct magic_enum::customize::enum_range { + static constexpr bool is_flags = true; +}; int main() { // Enum-flags variable to string name. @@ -48,7 +49,7 @@ int main() { // AnimalFlags names: HasClaws CanFly EatsFish Endangered // String name to enum-flags value. - auto f2 = magic_enum::enum_cast("EatsFish|CanFly"); + auto f2 = magic_enum::enum_flags_cast("EatsFish|CanFly"); if (f2.has_value()) { std::cout << "EatsFish|CanFly = " << magic_enum::enum_integer(f2.value()) << std::endl; // CanFly|EatsFish = 1074790400 } @@ -80,7 +81,7 @@ int main() { std::cout << " " << f; // Ostream operator for enum-flags. } std::cout << std::endl; - // AnimalFlags sequence: HasClaws CanFly EatsFish Endangered + // AnimalFlags values: HasClaws CanFly EatsFish Endangered using namespace magic_enum::bitwise_operators; // out-of-the-box bitwise operators for all enums. // Support operators: ~, |, &, ^, |=, &=, ^=. diff --git a/example/example.cpp b/example/example.cpp index 4c2cc48..dc838d6 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -23,6 +23,7 @@ #include #include +#include enum class Color : int { RED = -10, BLUE = 0, GREEN = 10 }; @@ -80,7 +81,7 @@ int main() { std::cout << " " << c; // Ostream operator for enum. } std::cout << std::endl; - // Color sequence: RED BLUE GREEN + // Color values: RED BLUE GREEN enum class Flags { A = 1, B = 2, C = 4, D = 8 }; using namespace magic_enum::bitwise_operators; // out-of-the-box bitwise operators for all enums. diff --git a/include/magic_enum.hpp b/include/magic_enum.hpp index 82eb42a..166c5b4 100644 --- a/include/magic_enum.hpp +++ b/include/magic_enum.hpp @@ -58,9 +58,6 @@ #if !defined(MAGIC_ENUM_USING_ALIAS_STRING_VIEW) #include #endif -#if !defined(MAGIC_ENUM_NO_STREAMS) -#include -#endif #if defined(__clang__) # pragma clang diagnostic push @@ -1467,81 +1464,6 @@ inline constexpr auto as_flags = AsFlags ? detail::enum_subtype::flags : detail: template inline constexpr auto as_common = AsFlags ? detail::enum_subtype::common : detail::enum_subtype::flags; -#if !defined(MAGIC_ENUM_NO_STREAMS) - -namespace ostream_operators { - -template = 0> -std::basic_ostream& operator<<(std::basic_ostream& os, E value) { - using D = std::decay_t; - using U = underlying_type_t; - - if constexpr (detail::supported::value) { - if constexpr (detail::subtype_v == detail::enum_subtype::flags) { - if (const auto name = enum_flags_name(value); !name.empty()) { - for (const auto c : name) { - os.put(c); - } - return os; - } - } else { - if (const auto name = enum_name(value); !name.empty()) { - for (const auto c : name) { - os.put(c); - } - return os; - } - } - } - return (os << static_cast(value)); -} - -template = 0> -std::basic_ostream& operator<<(std::basic_ostream& os, optional value) { - return value ? (os << *value) : os; -} - -} // namespace magic_enum::ostream_operators - -namespace istream_operators { - -template = 0> -std::basic_istream& operator>>(std::basic_istream& is, E& value) { - using D = std::decay_t; - - std::basic_string s; - is >> s; - if constexpr (detail::supported::value) { - if constexpr (detail::subtype_v == detail::enum_subtype::flags) { - if (const auto v = enum_flags_cast(s)) { - value = *v; - } else { - is.setstate(std::basic_ios::failbit); - } - } else { - if (const auto v = enum_cast(s)) { - value = *v; - } else { - is.setstate(std::basic_ios::failbit); - } - } - } else { - is.setstate(std::basic_ios::failbit); - } - return is; -} - -} // namespace magic_enum::istream_operators - -namespace iostream_operators { - -using namespace ostream_operators; -using namespace istream_operators; - -} // namespace magic_enum::iostream_operators - -#endif - namespace bitwise_operators { template = 0> diff --git a/include/magic_enum_iostream.hpp b/include/magic_enum_iostream.hpp new file mode 100644 index 0000000..1bb2a2d --- /dev/null +++ b/include/magic_enum_iostream.hpp @@ -0,0 +1,113 @@ +// __ __ _ ______ _____ +// | \/ | (_) | ____| / ____|_ _ +// | \ / | __ _ __ _ _ ___ | |__ _ __ _ _ _ __ ___ | | _| |_ _| |_ +// | |\/| |/ _` |/ _` | |/ __| | __| | '_ \| | | | '_ ` _ \ | | |_ _|_ _| +// | | | | (_| | (_| | | (__ | |____| | | | |_| | | | | | | | |____|_| |_| +// |_| |_|\__,_|\__, |_|\___| |______|_| |_|\__,_|_| |_| |_| \_____| +// __/ | https://github.com/Neargye/magic_enum +// |___/ version 0.8.2 +// +// Licensed under the MIT License . +// SPDX-License-Identifier: MIT +// Copyright (c) 2019 - 2023 Daniil Goncharov . +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef NEARGYE_MAGIC_ENUM_IOSTREAM_HPP +#define NEARGYE_MAGIC_ENUM_IOSTREAM_HPP + +#include "magic_enum.hpp" +#include + +namespace magic_enum { + +namespace ostream_operators { + +template = 0> +std::basic_ostream& operator<<(std::basic_ostream& os, E value) { + using D = std::decay_t; + using U = underlying_type_t; + + if constexpr (detail::supported::value) { + if constexpr (detail::subtype_v == detail::enum_subtype::flags) { + if (const auto name = enum_flags_name(value); !name.empty()) { + for (const auto c : name) { + os.put(c); + } + return os; + } + } else { + if (const auto name = enum_name(value); !name.empty()) { + for (const auto c : name) { + os.put(c); + } + return os; + } + } + } + return (os << static_cast(value)); +} + +template = 0> +std::basic_ostream& operator<<(std::basic_ostream& os, optional value) { + return value ? (os << *value) : os; +} + +} // namespace magic_enum::ostream_operators + +namespace istream_operators { + +template = 0> +std::basic_istream& operator>>(std::basic_istream& is, E& value) { + using D = std::decay_t; + + std::basic_string s; + is >> s; + if constexpr (detail::supported::value) { + if constexpr (detail::subtype_v == detail::enum_subtype::flags) { + if (const auto v = enum_flags_cast(s)) { + value = *v; + } else { + is.setstate(std::basic_ios::failbit); + } + } else { + if (const auto v = enum_cast(s)) { + value = *v; + } else { + is.setstate(std::basic_ios::failbit); + } + } + } else { + is.setstate(std::basic_ios::failbit); + } + return is; +} + +} // namespace magic_enum::istream_operators + +namespace iostream_operators { + +using namespace ostream_operators; +using namespace istream_operators; + +} // namespace magic_enum::iostream_operators + +} // namespace magic_enum + +#endif // NEARGYE_MAGIC_ENUM_IOSTREAM_HPP diff --git a/test/test.cpp b/test/test.cpp index 986c6d8..c6cb96e 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -29,6 +29,7 @@ #define MAGIC_ENUM_RANGE_MAX 120 #include #include +#include #include #include diff --git a/test/test_flags.cpp b/test/test_flags.cpp index c51b1bd..9a960a1 100644 --- a/test/test_flags.cpp +++ b/test/test_flags.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include diff --git a/test/test_nonascii.cpp b/test/test_nonascii.cpp index 83ad14d..af1b27f 100644 --- a/test/test_nonascii.cpp +++ b/test/test_nonascii.cpp @@ -29,6 +29,7 @@ #define MAGIC_ENUM_RANGE_MAX 120 #include #include +#include #include #include