mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 16:56:42 +08:00
Overloaded stream operators.
To avoid paying the huge penalty of including iostream and string for users that don't need those headers, and to avoid creating a second, optional header file, I resorted to defining the operators as templates to prevent type checking until the user tries to actually use them. The stream types and strings are wrapped in a metafunction that depends on the template parameter. This is basically a hack, but it seems to work.
This commit is contained in:
parent
4314ad3fd3
commit
0f63667106
52
enum.h
52
enum.h
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iosfwd>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
@ -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
|
||||||
|
// <iostream> or <string>, 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 <iostream> and/or <string>. 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 <type_traits> is not
|
||||||
|
// available in C++98.
|
||||||
|
template <typename T, typename Enum>
|
||||||
|
struct hide { typedef T type; };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Enum>
|
||||||
|
inline typename better_enums::hide<std::ostream,
|
||||||
|
typename Enum::_enumerated>::type&
|
||||||
|
operator <<(std::ostream& stream, const Enum& value)
|
||||||
|
{
|
||||||
|
return stream << value._to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Enum>
|
||||||
|
inline typename better_enums::hide<std::istream,
|
||||||
|
typename Enum::_enumerated>::type&
|
||||||
|
operator >>(typename better_enums::hide<std::istream, Enum>::type& stream,
|
||||||
|
Enum& value)
|
||||||
|
{
|
||||||
|
typedef typename better_enums::hide<std::ios_base, Enum>::type ios_base;
|
||||||
|
typedef typename better_enums::hide<std::string, Enum>::type string;
|
||||||
|
|
||||||
|
string buffer;
|
||||||
|
|
||||||
|
stream >> buffer;
|
||||||
|
better_enums::optional<Enum> 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
|
#endif // #ifndef BETTER_ENUMS__ENUM_H
|
||||||
|
|||||||
29
test/cxxtest/stream.h
Normal file
29
test/cxxtest/stream.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <cxxtest/TestSuite.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <enum.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user