On Wed, 18 Apr 2018 06:11:35 -0700 (PDT), Luca wrote:
> What kind of "synchronization" should I expect between std::cin and
> stdin? To which extent they can be used interchangeably? For
> instance, should the set flags associated with them (like the
> end-of-file) be the same?
>
> What does the standard say about using these two objects in the same
> program? The only thing I could find is [narrow.stream.objects]/1
> <
https://timsong-cpp.github.io/cppwp/iostream.objects#narrow.stream.objects-1>,
> but is is not clear to me what does the wording exactly mean.
For reference, here is that wording:
The object cin controls input from a stream buffer associated with
the object stdin, declared in <cstdio>.
From my perusal of the Standard, that sentence is indeed all that is
said on the matter. Here are my thoughts:
> What kind of "synchronization" should I expect between std::cin and
> stdin?
I think you can expect that `std::cin' (or, rather, its underlying
stream buffer) keeps itself coherent with `stdin'; however, `stdin'
probably doesn't know anything about `std::cin' (or its underlying
machinery) and thus does not keep itself coherent with `std::cin' (or
its underlying machinery).
> To which extent [can they] be used interchangeably?
Given that the Standard says nothing else, you must assume that it
would be incredibly unwise to use both `std::cin' and `stdin' manually
at the same time.
If you use both at the same time, then you are treating `stdin' as a
shared resource; it is being shared between the code that uses
`std::cin' and the code that uses `stdin' directly. Your only hope of
producing a working, portable program is to use that shared resource
very carefully, and the Standard implies that the only way to use that
shared resource very carefully is to ensure that `std::cin' is the
sole user of `stdin'.
That is, in general, you cannot use them interchangeably.
That being said, the rule about synchronization comes into play: If,
for a time, you use only `std::cin', then at the end of that time,
both `std::cin' and `stdin' will be properly "synchronized" with each
other. I suppose that you may thereafter start using `stdin' directly;
however, you must assume that doing so puts `std::cin' and `stdin' out
of synchronization---it's a one-way street, and you may never safely
go back to using `std::cin'. Even then, when your program ends, it
will call the destructor of `std::cin', which means that your program
could try to go back down that one-way street and end up being very
confused; your program could crash on exit, or something silly like
that.
> For instance, should the set [of] flags associated with them[...] be
> the same?
That would be an implementation detail. Maybe `std::cin' sets up
`stdin' to be used in raw "binary" mode, and then performs its own
post-processing on the characters that are read; or, maybe `std::cin'
passes on shared flags to `stdin' and thereby allows `stdin' to handle
most of the processing.
You'd have to check at run-time that `stdin' is in a certain desirable
state, or you'd have to write code that is specific to a particular
implementation.
In short, use one or the other, but not both, unless you are writing
code that is specific to a particular implementation that you
understand really well.
Sincerely,
Michael Witten