,

On Sun, 25 Jun 2023, 02:44 Kevin Schmidt via Std-Proposals, <std-proposals@lists.isocpp.org> wrote:
Thanks for your feedback, they are certainly valid concerns I may have not fully thought out. You definitely mentioned some cracking points. I'll explain my thoughts further:

On 6/25/23 01:21, Jonathan Wakely via Std-Proposals wrote:
I think the proposal should explain/discuss why that is better than:
if (opt)
  is >> *opt;
else {
  T val;
  if (is >> val)
    opt.emplace(val);
}
i.e. why should it change the state of the optional if reading from the stream fails? Why should it always emplace a new object even if the optional already contains a value?
 
I think we should always emplace() a new object and one argument is that it's in line with the semantics of streaming operators. When you read into a variable using an istream, you generally expect the old value to be replaced, not modified.

Do you? What does it mean for an int or std::string to be replaced rather than modified? To me that would imply destroying the object and recreating a new one in its memory. That's not what reading into a std::string does, but it's what using optional::emplace would do.

In concrete terms,  this reuses the memory of the string (if it doesn't need more than 100 bytes) it doesn't replace it:

std::string str;
str.reserve(100);
std::cin >> str;

Maybe your suggestion makes sense for optional, my point is that you need to give justification for it.



This would hold for std::optional as well, I would say. Concerning the resetting of the optional if reading from the stream fails, the rationale is to clearly indicate that no valid data was loaded into the optional. The absence of a value can be a meaningful signal in this case,

The stream state is set to failbit, that gives you the signal.

Most standard operator>> overloads avoid altering the object on error.

but I do agree that there could certainly be use cases where the preservation of the existing value (if any) could be preferred, although I would expect to receive the new value in the optional, or receive nullopt, indicating an error occurred.

How?
 
Well this would be dependent on the standard implementation. I just wanted to highlight the possibility to avoid the unnecessary allocation of the stack object "T value", that I mentioned. The managed value could be directly set, instead of emplaced and then implicitly set, both are valid approaches.

Unless I'm mistaken, you can't stream into a variant. You can only stream into an already active alternative. Which is similar to optional, where you can only stream into a contained value (not into a disengaged optional).
 
You are correct, my mistake, I checked it again on cppreference. Must've mixed something up. Currently, std::variant does not have a streaming operator defined. I made a wrong comparison. The aim, however, is to make std::optional as flexible and intuitive as possible to work with.

What other stream types do you mean?
 
For the reference to other stream types, I was considering the idea of serialization and deserialization in other formats, like binary. Though overloads for std::istream are most relevant and other 'stream types' might have been an overstatement. Excuse me there.

There are no other stream types in the standard library, so I don't think it's useful to discuss them in this proposal.