The Default Constructible Type Requirement

| Home | Libraries | People | FAQ | More

#### 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
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