Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

The Default Constructible Type Requirement

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] Note

By default the boost::cnv::cstream and boost::cnv::wstream converters require the TypeOut type to be Default Constructible.

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

PrevUpHomeNext