...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Due to std::stream
design it requires an initialized
temporary storage of TypeOut type to put the result
of the requested conversion to. Conceptually boost::cnv::cstream
achieves that with:
istream_type& istream = stream_; TypeOut result = boost::make_default<TypeOut>(); istream >> result;
The temporary storage result
is initialized with boost::make_default()
the default implementation of which is
namespace boost { template<typename T> T make_default() { return T(); } }
Consequently,
Note | |
---|---|
By default the |
That said, a well-designed type (in my opinion, anyway) should only have meaningful and unambiguous constructors... and the default constructor is not always and necessarily one of them. Consider the following as one such example:
struct direction { // Note: the class does NOT have the default constructor. enum value_type { up, dn }; direction(value_type value) : value_(value) {} bool operator==(direction that) const { return value_ == that.value_; } value_type value() const { return value_; } private: value_type value_; };
std::istream& operator>>(std::istream& stream, direction& dir) { std::string str; stream >> str; /**/ if (str == "up") dir = direction::up; else if (str == "dn") dir = direction::dn; else stream.setstate(std::ios_base::failbit); return stream; } std::ostream& operator<<(std::ostream& stream, direction const& dir) { return stream << (dir.value() == direction::up ? "up" : "dn"); }
The direction
type has
no default state. It is not Default
Constructible and, consequently, the following does
not compile:
direction dir1 = convert<direction>(str, cnv).value(); // Does not compile direction dir2 = lexical_cast<direction>(str); // Does not compile
However, Boost.Convert is able to handle such a type with little help from the user -- the instructions how to create that mentioned temporary storage:
namespace boost { template<> inline direction make_default<direction>() { return direction(direction::up); } }
Now such class can be deployed with boost::cnv::cstream
:
direction dir1 = convert<direction>(str, cnv).value(); // Compiles direction dir2 = lexical_cast<direction>(str); // Does not compile