<div dir="ltr">I think mixing text and binary in the same layer is the fatal flaw of iostream.<div>A binary stream that offers more than a bag of bytes would suffer the same issue as iostream.</div><div><br></div><div>Separation of text, locales and bytes at different layers is really important</div><div><br></div><div>If you have a binary_stream object and you can somehow set a bom on it, which not only is text specific, but worse, Unicode specific, something has gone wrong</div><div><br></div><div>When reading, we can implicitly handle bom and UTF-X -&gt; UTF-Y conversion</div><div>and moves the state from the stream to the view</div><div><br></div><div>view = stream | asUtfX</div><div><br></div><div>when writing, having transcoding handle the bom let you handle the case where the text already has a bom without introducing a state on the stream.</div><div><br></div><div>text | toUtf8BOM &gt;&gt; stream </div><div>text | toUtf16BOM(stream.endianness) &gt;&gt; stream <br></div><div><br></div><div>&gt; stdout is a special case</div><div>I don&#39;t believe it is, and I believe iostream should not have made this assumption.</div><div><br></div><div>Maybe consoles are a special case, and maybe the best way to handle them would be to have an encoding-aware console API.</div><div><br></div><div>But short of that stdin/out deal with bag of bytes and text abstractions should be</div><div>layered on top rather than baked in.</div><div><br></div><div>Another solution would be to have both text_stream and binary_stream, but as you say, cout can be either depending on use cases</div><div><br></div><div><br></div><div>Note that everything that applies to text probably applies to everything else</div><div>Serialization of a given arbitrary type on a stream should depend on the specifics of the application rather than be a property of the stream.</div><div><br></div><div>stream.write(std::as_bytes(date));</div><div>vs</div><div>stream.write(date);</div><div><br></div><div>The later is arguably nicer but gives no control to applications over how things are serialized. </div><div><br></div><div><br></div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 7 Feb 2019 at 12:42 Lyberta &lt;<a href="mailto:lyberta@lyberta.net">lyberta@lyberta.net</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Corentin:<br>
&gt; 1/  Text _is_ bytes. Unicode specifies BOM and little/big endian versions<br>
&gt; so I think prepending a bom ( should you want to ) and byte-swapping can be<br>
&gt; done along transcoding<br>
<br>
Maybe separate BOM handling into a format state of the stream. Consider<br>
this:<br>
<br>
enum class std::bom_handling<br>
{<br>
        none, ///&lt; Do not read or write BOM.<br>
        not_utf8, ///&lt; Read and write BOM only in UTf-16 and UTF-32.<br>
        all ///&lt; Read and write BOM in all 3 encoding forms.<br>
};<br>
<br>
BinaryOutputStream&amp; stream;<br>
stream.GetFormat().SetBOMHandling(std::bom_handling::all);<br>
<br>
This feels like a more elegant design because it separates concerns better.<br>
<br>
&gt; <br>
&gt; 3/ stream don&#39;t have an explicit encoding ( or locale, for that matter ),<br>
&gt; but they might expect one - think for example about writing to stdout.<br>
<br>
stdout is a special case and we have a way to handle it - execution<br>
character set. The only problem is that in order to go from Unicode to<br>
ECS right now you&#39;d need to use std::codecvt which is a horrible mess.<br>
<br>
Still, there are some utilities that treat stdin/stdout as a stream of<br>
raw bytes so it doesn&#39;t always represent a text stream.<br>
<br>
_______________________________________________<br>
SG16 Unicode mailing list<br>
<a href="mailto:Unicode@isocpp.open-std.org" target="_blank">Unicode@isocpp.open-std.org</a><br>
<a href="http://www.open-std.org/mailman/listinfo/unicode" rel="noreferrer" target="_blank">http://www.open-std.org/mailman/listinfo/unicode</a><br>
</blockquote></div></div></div>