
Hi Andrew, I was in the middle of the pre-vacation rush when this thread started. Now I'm back from vacations, so I can finally take a serious look into the subject :) Your requirement is to be able to do something like this: istringstream in ("test"); optional<string> s; assert (s); It fails with the current "optional_io.hpp" implementation because it uses an explicit encoding to indicate the initialization state in the code as a way to guarantee a closed roundtrip conversion from and to an uninitialized optional *wihtout any dependency on the encoding used by the underlying type* That is, the current optional_io.hpp is explicitely not designed to support your use case. Instead, it is designed to support the following use case: optional<T> in = -value_or_empty- stream << in ; optional<T> out ; stream >> out ; assert( in == out ) ;
Andrew Troschinetz <ast <at> arlut.utexas.edu> writes:
On Feb 26, 2009, at 10:00 AM, Robert Ramey wrote:
The fact that the serialization of optional is implemented and tested as part of the serialization library is an anomoly. In fact, this code and test should be moved into the optional library.
Serialization and optional_io have different approaches.
Considering the current "optional_io.h", not really.
We refuse to read/write an uninitialized object
Which is a reasonable requirement in the context of lexical_cast.
while serialization encode whether an object is initialized or not.
And so does "optional_io.h"
But why move the get pointer up by one? Why one? Does this make sense? I can't provide a reasoning as to why it does, if it does.
Please don't guess about iostream implemenation details. All we need is a consistency with underlying type
That's not all.. you also need a way to detect an unitialized value. You proposal uses extraction failure for that because it works perfectly fine in the context of lexical_cast since the stream contains exclusively the given optional (possibly empty) and nothing else. But if the stream can contain other items then you need an explicit marker. I don't think both requirements are compatible. Consider the following: stringstream stream ; optional<double> ind ; // <= empty optional<string> ins("123"); stream << ind << ins ; optional<double> outd ; optional<string> outd ; stream >> outd >> outs ; assert( ind == outd ) ; assert( ins == outs ) ; That would fail using your implementation because the stream would only contain 123 which just coincidentally represents a valid double, so in the extraction state the string instead of the double will be empty. This is what happens when failure to extract is used to indicate an empty optional. This deeply depends on the encoding detais of the underlying type. For example, in one of Andrew's use cases, there is a sequence of numbers and not-numbers. Just incidentally, since not-numbers fail to extract as numbers, that works. I recall very well now having this very same discussion on the distant past. It used to be as you want it, but for the sake of the serialization library I choose the current semantics, precisely because as Robert indicated the serialization library doesn't explicitely depend on Boost.Optional. Without any explicit dependency, optional<> *itself* needs to provide roundtrip IO functions not depending on EOF or the encoding details of the underlying type for uninitialized optionals. I implemented the IO operators in a separate header precisely to allow users to provide the other semantics, but that of course doesn't work if such a header ends up in another general utility like lexical_cast or the serialization headers. Off the top of my head, I think the best course of action would be for you to provide your implementation in "optional_io.h" but within a separate namespace, like lexical_cast_detail or so, keeping the current operators untouched. Then within the lexical_cast function a "using lexical_cast_detail;" would resolve to the proper IO operators. HTH -- Fernando Cacciola SciSoft Consulting http://www.scisoft-consulting.com