I would be very interested to read some educated speculation concerning why there is no c++ standard way to handle unbuffered input, e.g. something like getch + kbhit. For literally decades, innumerable c++ console programmers have sought a way to simply implement, "Press any key to continue..." The fact that this is still not available in a standard library seems so unlikely and perverse that I am inclined to wonder if it is conspiratorial.

This doesn't seem necessarily any more platform-dependent than the other aspects of I/O that the standard does address. It is not like graphics, in which assumptions must be made about hardware capabilities. Its functional domain is more akin to that of standard iostream, in that it is expletive deleted exactly the same thing, but without waiting for the enter key. I presume that it would be relatively trivial to add this to the existing I/O standard.

Likewise, it doesn't seem to be any less essential than other modes of I/O. I think that almost every console programmer has investigated a way to do it, most consider adopting a non-standard method because it is the only option, and a significant fraction of us have extensively used non-standard methods. How does this not qualify for inclusion in the standard while something like expletive deleted "get_money" does? Though I'm sure it is not, it nonetheless superficially seems quite arbitrary.

Is this simply a huge oversight? If not, what are the technical reasons for why this cannot be standardized? And if it could be standardized, and if it has been considered by those who influence the standard, then who is responsible for all these years of suffering without it? And I mean who exactly, as in names and contact info, preferably recent photographs, home addresses, and daily schedules.

P.S.: Please forgive my improprieties, but I am feeling particularly disinclined to disguise my wroth demeanor concerning this matter.

Recommended Answers

All 5 Replies

Are you really just joking? It's a question I see every so often.

If I had to guess, I'd say that because it's not physically possible on every system, and there's no way for the writers of the standard to guarantee that everyone will be using an input method that supports unbuffered input, nobody wants to screw those chaps over by suddenly demanding the impossible. C and C++ have an abstract view of what counts as input and output, deliberately so. You could make some demands about the kind of system C++ is to run on, but given that the current setup works well, with the standard leaving things that involve the physicalities of the system to be done specifically for each system, breaking it wouldn't do anyone any favours and would render some systems suddenly no longer possible to have a compliant implementation on.

I know Andrew Koenig used to post here and he's pretty well informed about this sort of thing; he was heavily involved in the C++ standards committee. Maybe we'll get lucky; he'll see this thread and he can give us the definitive answer.

I see. No, I wasn't joking. It's lack of standardization deeply disturbs me. I it bothered me enough that I needed to understand the justification. Therefore, I thank you for taking the time to bestow some c++ knowledge on me today. :D

I'd definitely appreciate some more info though, while I have a moment. Could you explain the impossibility in technical terms?

I'm sorry if it seems obvious. I sometimes tend to overlook the obvious. In fact, I once spent almost five minutes looking for my car keys just to find them in my right hand. I have a reputation for it.

Thank you again for your patience and your quick reply.

I asked about the jokingness because of your signature :p "I'm just joking, of course, but wouldn't it be funny if I weren't?" I guess you're joking about pushing Stroustrup over in the park :)

I am literally just on my way out the front door to scavenge food, but off the top of my head some systems have terminal interfaces, for example, that do not even pass the input line onwards until the user has pressed "enter". The data does not leave the input device until then. Specifying that the CPU do something as the user types would seem a bit unfair. Without knowing much about your system, this could be simialr to how your terminal works; you type into an OS provided box, and the OS thinks about passing that data onwards. You can ask the OS to pass it on immediately, but you do that via an OS specific API. That API cannot be specified in the C++ standard as the C++ standard is a programming langauge definition; not a demand on how your OS should work.

The language standard and the standard library is developed as a negociation between implementors (who need to comply to it) and users (who want features from it). If the amount of users that request a particular feature very strong and all implementors have little or no problem providing it (they often provide it already, just not in a standardized way), then it can go into the standard.

In this case, there isn't much need for unbuffered streams. Any kind of serious reading / writing operations involving files (or, equivalently, cin / cout) will need to be buffered. And there are only very rare occasions (mostly "toy" console programs) where an unbuffered input would be useful (mostly in making the program nicer, but usually not critical to its operation).

Then, how can you specify that the stream should be unbuffered? There are always buffers everywhere. There are usually hardware-cache chips at both ends of a SATA connection, there is buffering done by the operating system on most file I/O operations (and terminal / console I/O is usually implemented via files, or virtual files), and heck, there is also multiple levels of caching (L1, L2, L3) between RAM and the CPU. In this kind of environment, what is "unbuffered"?

Do you mean that there isn't buffering done in user-space (e.g., under the hood of iostream or printf/scanf)? But that still doesn't eliminate the buffering done in kernel-space, in the CPU architecture and at the hardware level. So, even if the standard had a version of streams that was required to be implemented without a user-space buffer, it still wouldn't have much practical meaning in terms of how immediate the reception of the data would be, but it would only have practical meaning in terms of how poorly you can expect it to perform (no user-space buffering means a lot of latency in making kernel-space calls). And, of course, the standard cannot specify such a thing because the language standard and all its specifications have absolutely no concept of user-space vs. kernel-space (and is pretty oblivious to most similar issues too). For instance, there cannot be even a concept of an operating system being in existence, since C++ can be used in environments that don't even have an operating system running, it can even be used to implement the operating system itself. In other words, the notion that the standard has of the machine on which it is running is a much too abstract and simple to allow for this kind of specifications.

So, what the standard would have to require of the implemention is to implement an "unbuffered" streaming, meaning reading a byte in the code leads to an immediate readout of the physical source of the byte (HDD, network, console, etc.) without any intervening buffer (at any level). And of course, "immediate" in the computer world means "within a finite amount of time which is bounded by some deterministic upper-bound". This pretty much impossible for most streaming tasks on most systems, this can't happen for file I/O anywhere, this can't happen for console I/O anywhere, this can't happen for anything that has to go through a network (e.g., what if I remote-login to a computer and run the program, how could it possibly receive an "unbuffered" input), and so on. There are only a few areas and a few types of systems where there can be some guarantees along those lines, most system never provide any such guarantee even when using OS-specific functions like getch or whatever else. At best, they can guarantee no user-space buffering, and maybe some expected kernel-space latency, but that's about it. So, if the C++ standard were to require unbuffered stream, not a single system could really comply with such a requirement.

Now, since the standard cannot make a difference between hardware vs. software buffering, or between user-space vs. kernel-space buffering, all it can say is "there is going to be buffering". And if you don't have the requirement for an "immediate" stream, then there is usually great benefit in implementing some user-space buffering. By the way, the standard doesn't require that the streams be buffered, it simply allows them to be and puts the mechanism in place (i.e., streambuf base-class). Some implementations may decide to have no buffering in place, some may provide an alternative non-standard streambuf class to handle unbuffered operations, and you can even write a streambuf class that involves no user-space buffering. This still won't solve the problem of all the other buffers that you can't do anything about.

This is a little bit like saying, "it would be easier to parallel-park if the wheels were facing sideways", it's true, but it wouldn't be a great trade-off to have a car that is easy to parallel-park but is unusuable for anything else. Operating systems and computers, and consequently, programming languages, are designed we the main purposes in mind, i.e., the tasks that they do 99.99% of the time. In this case, computers mostly process a lot of data and need efficient data-transports, and lots of layers of buffering to make everything run smoothly. Something like requiring an immediate byte-per-byte transport of data is just going too much against the fibers of a computer system, and even though it seems like it should be easy to do, it is not. And systems provide some means to do that for user-input in the console, because this is one case where it's somewhat do-able (not strictly-speaking, but only loosely so). But this is just too odd of a case and has too little application to really mandate that it would be somehow chiseled into the standard (which would be technically difficult to do, due to the aforementioned non-triviality of the concept of "unbuffered").

While what mike_2000_17 said is all correct, the real reason is actually a lot simpler: C++ has no concept of console I/O because C++ - and many of the operating systems it operates under, including Unices - has no concept of a console. More importantly, C++'s standard libraries operates primarily on abstract streams rather than devices, and has no way of knowing if a given stream is a dumb terminal, a file, a network socket, or a window in a windowing environment. These are all system-dependent definitions. Not all systems have consoles, just as nt all systems have files, or network connections - again, consider the case of an embedded controller.

Moreover, the capabilities of a console vary from system to system, and not in trivial ways. You have to recall that the original Unix system worked primarily with TTYs, literal teletypes that printed output to a roll of paper. Even when more advanced consoles were available - which they were, even in 1967 - there was no standardization as to what operations they could perform. How do you handle the case of 'move the cursor to screen location (x, y)' when you don't know if the terminal in question is even capable of doing so, or even if it has a screen at all? While libraries like termcap and curses were eventually developed to work with different kinds of terminals in a uniform fashion, they couldn't be made part of the language because it would require thousands of different parameters to be handled.

Which brings us to the real core of the issue: simplicity. C++, for all it's compexity, generally follows the C development rule of not making assumptions about the underlying system it is running on. This is the same reason that threading was not introduced into the language until the most recent round of language development, and it was a hotly debated matter even so. Generally speaking, C++ tries to avoid doing anything in the stadard library which might not be available on some of the possible platforms.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.