diff --git a/enum.h b/enum.h index 745b63e..02e7345 100644 --- a/enum.h +++ b/enum.h @@ -10,6 +10,7 @@ #include #include +#include #include @@ -1038,4 +1039,55 @@ BETTER_ENUMS__CONSTEXPR inline bool operator !=(const Enum &a, const Enum &b) \ +namespace better_enums { + +// This template is used both as a sort of enable_if for SFINAE, and to delay +// the compiler from type-checking certain expressions. enum.h does not include +// or , because those headers parse very slowly. Therefore, +// it is necessary to prevent the compiler from trying to do anything with types +// from those headers unless the operators <<, >> are actually used, by which +// point the user is expected to have included and/or . The +// alternative is to simply move the operator definitions into a separate add-on +// header file. +// +// It should be possible to use std::enable_if, however is not +// available in C++98. +template +struct hide { typedef T type; }; + +} + +template +inline typename better_enums::hide::type& +operator <<(std::ostream& stream, const Enum& value) +{ + return stream << value._to_string(); +} + +template +inline typename better_enums::hide::type& +operator >>(typename better_enums::hide::type& stream, + Enum& value) +{ + typedef typename better_enums::hide::type ios_base; + typedef typename better_enums::hide::type string; + + string buffer; + + stream >> buffer; + better_enums::optional converted = + Enum::_from_string_nothrow(buffer.c_str()); + + if (converted) + value = *converted; + else + stream.setstate(ios_base::failbit); + + return stream; +} + + + #endif // #ifndef BETTER_ENUMS__ENUM_H diff --git a/test/cxxtest/stream.h b/test/cxxtest/stream.h new file mode 100644 index 0000000..18b2df8 --- /dev/null +++ b/test/cxxtest/stream.h @@ -0,0 +1,29 @@ +#include +#include +#include + + + +ENUM(Compiler, int, GCC, Clang, MSVC) + + + +class StreamOperatorTests : public CxxTest::TestSuite { + public: + void test_output() + { + std::stringstream stream; + + stream << +Compiler::GCC; + TS_ASSERT_EQUALS(strcmp(stream.str().c_str(), "GCC"), 0); + } + + void test_input() + { + std::stringstream stream("Clang"); + Compiler compiler = Compiler::GCC; + + stream >> compiler; + TS_ASSERT_EQUALS(compiler, +Compiler::Clang); + } +};