C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Add operator>> overloads to std::optional for streaming input

From: Kevin Schmidt <kevin_at_[hidden]>
Date: Sun, 25 Jun 2023 03:37:07 +0200
Thank you for your feedback.

On 6/25/23 01:32, Andrey Semashev via Std-Proposals wrote:

> This means you cannot read an empty optional from the stream.
>

Indeed, as currently proposed, there's no way to read an empty optional
from the stream. An approach to handling this could be to introduce a
keyword or sentinel value which, when read from the stream, sets the
std::optional to empty.

Also, if you introduce an operator>>, it is only natural to introduce an
> operator<< as well.
>

I agree, but in the initial proposal, I just mainly focused on streaming in
for simplicity, though I do agree that an operator<< would help make the
API more symmetric.

void test(std::optional<int> o1)
> {
> std::stringstream strm;
> strm << o1 << " 0";
> std::optional<int> o2;
> strm >> o2;
> assert(o1 == o2); // fails for certain o1 values
> }
>

This is indeed a good point, it would be ideal to maintain a perfect
roundtrip. One approach could be defining a special format for
serialization and deserialization of std::optional. This would mean
specifying a way to serialize an empty optional.

I suggest you to have a look at Boost.Optional, which does support IO. Note
> that it defines its operators differently from what you propose, and allows
> for the roundtrip to work.
>

In the case of my proposed implementation for std::optional, I'm suggesting
adopting a similar approach for handling I/O operations. The idea is to
define a specific format that can represent both populated and empty
optional values.
I already kind of explained it in another reply, but I'll elaborate:

Boost.Optional enables I/O operations on optional types by defining a
specific format for both serialization and deserialization, including
special handling for uninitialized or empty optionals. This ensures a
correct roundtrip. For instance, we could use a certain sentinel value or
marker to represent an empty std::optional in the stream. When reading from
the stream, if this sentinel value is encountered, it's understood that the
optional is empty. On the other hand, when writing to the stream, if the
optional is empty, this sentinel value is written.

This way we could achieve a similar roundtrip property as Boost.Optional.


> No it can't because it would require changing the interpretation of the
> input string, and that would be a breaking change.
>

I didn't mean to change the interpretation. I was talking about the way the
operator>> is implemented. What I meant was that the example I gave could
be adjusted to better fit into the standard, so as to not define an
unnecessary temporary variable for example.

Thanks again for your feedback.

Am So., 25. Juni 2023 um 01:32 Uhr schrieb Andrey Semashev via
Std-Proposals <std-proposals_at_[hidden]>:

> On 6/25/23 01:37, Kevin Schmidt via Std-Proposals wrote:
> > Hello everybody, I would like to propose the following for the new
> standard:
> >
> > Motivation:
> >
> > Currently, std::optional does not have an operator>> defined, so values
> > cannot be streamed directly into an std::optional. Users have to
> > explicitly extract the value from the stream and assign it to the
> > std::optional using emplace() or operator=(). By adding operator>>
> > overloads, std::optional can support more intuitive streaming input.
> >
> > Initial Design Proposition:
> >
> > template <typename T>
> > std::istream& operator>>(std::istream& is, std::optional<T>& opt) {
> > T value;
> > if (is >> value) {
> > opt.emplace(value);
> > } else {
> > opt.reset();
> > }
> > return is;
> > }
> >
> > This defines an operator>> that extracts a value of type T from the
> > input stream "is" and assigns it to the std::optional<T> object "opt".
> > If the extraction succeeds, the value is emplace()d into "opt". If it
> > fails, "opt" is reset to an empty state.
>
> This means you cannot read an empty optional from the stream.
>
> Also, if you introduce an operator>>, it is only natural to introduce an
> operator<< as well. However you define it, if operator>> is defined as
> you propose, a perfect roundtrip is not possible:
>
> void test(std::optional<int> o1)
> {
> std::stringstream strm;
> strm << o1 << " 0";
> std::optional<int> o2;
> strm >> o2;
> assert(o1 == o2); // fails for certain o1 values
> }
>
> I suggest you to have a look at Boost.Optional, which does support IO.
> Note that it defines its operators differently from what you propose,
> and allows for the roundtrip to work.
>
> The roundtrip property is important for serialization purposes, which is
> also the primary use case for operator>>. It is not important for
> diagnostic output, which is one of the use cases for operator<<. Due to
> the roundtrip requirement, the output format of Boost.Optional might not
> be very nice-looking in diagnostic output, which is probably why it was
> not adopted by the standard.
>
> > The proposed design has been kept simple,
> > but can be extended in the future if needed.
>
> No it can't because it would require changing the interpretation of the
> input string, and that would be a breaking change.
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-06-25 01:37:21