The problem I am having with this is that our example is fundamentally broken code — as such it is not something that demonstrates any actual need for an update to the language.
For starters:
• The variable
i
is local to the loop, and consequently not available after! (What was the point of obtaining a value, then?)
• Input is not properly obtained. (Using
>>
for user input is Always Wrong™. I’ve written countless posts here about it.)
• Looping for the user to input correctly is the Wrong Thing To Do™. I touched on this already. Either input succeeds and the program moves on or it should fail, notify the user, and
go back to the prior menu/input wait state/whatever.
• The loop fails to terminate if user input is bad
for multiple reasons. (See also point #2.)
• The loop lacks basic entry checks, but I will generously waive this as “done already and not topic of conversation about loop syntax”, even though I don’t perceive it to have been considered. (For example, what if
ms1
contains no
i
that the user can input?)
User input is, frankly and quite seriously, one of the more difficult things to get right. I could design an entire university-level course on it. Somehow, however, it is never quite properly addressed — not in any textbook or online resource or college course I have ever seen or heard of. Somehow it is one of those things always assumed to be obvious, but it is anything but obvious...
Consequently we get untold collections of people online asking questions about how to fix things like
cin >> i
. You fix it by never doing it like that.
Were I to write a simple program desiring input of some known number, it would look one of two ways.
(1) standard sequential “do this then that and so on” kind of programs:
1 2 3 4
|
auto i = ask_integer( "Enter the number you know I know about that you want me to do something with: " );
if (!i) throw error( "That wasn't a number." );
if (!ms1.count(*i)) throw error( "I don't know anything about that number." );
do_something_with_the_integer( *i );
| |
(2) stateful kind of program, like stuff that has menus to do things, etc
1 2 3 4 5 6 7
|
void my_menu_function()
{
auto i = ask_integer( "Gimme the int you wanna use to do stuff with yer data: " );
if (!i) return message( "That weren't no number." );
if (!ms1.count(*i)) return message( *i, " not found!" );
do_something_with_the_integer( *i );
}
| |
Both of those examples obviously make use of constructs that require additional programming elsewhere, like the
ask_integer()
function.
1 2 3 4 5 6 7 8
|
std::optional <int>
ask_integer( const std::string & prompt )
{
std::cout << prompt;
std::string s;
getline( std::cin, s );
return string_to <int> ( s );
}
| |
Heck, you could make that even nicer by making it a templated function. This would give the compiler options to truly optimize it and give you a smaller binary.
1 2 3 4 5 6 7 8 9
|
template <typename T>
std::optional <T>
ask_input( const std::string & prompt )
{
std::cout << prompt;
std::string s;
getline( std::cin, s );
return string_to <T> ( s );
}
| |
And for the sake of completeness, here is the most basic version of that “try to get a T out of whatever the user typed” function, all encapsulated in its own little function nice and pretty-like:
1 2 3 4 5 6 7 8 9
|
template <typename T>
auto string_to( const std::string & s )
{
T value;
std::istringstream ss( s );
return ((ss >> value) and (ss >> std::ws).eof())
? value
: std::optional <T> { };
}
| |
Looks simple, don’t it? Looks can sure be deceiving.
In any case, we again find that life is made simpler by a utility functions that help us out.
But we also find that there is no free lunch. If you want pretty one-liners, you’ve got to do something somewhere else to make that happen. And that is a fundamental truth to all programming and programming languages!
It stands out in C and C++ because they are both significantly more low-level than something like, say, Python. Modern C++ gives us some powerful tools in the Standard Library, like the Ranges library, but the reality is that anywhere you see pretty it is because there is a lot of very carefully crafted code behind the scenes making that happen.
And we, as programmers, have to play both sides of that. We create something, a class, or a command-line program, that presents a nice interface to some user —whether it be another programmer or some five-year-old kid standing on the chair so he can reach the
Enter key— but we spend our time on the behind-the-scenes that the user never sees.
Anyway, my point was that I think it is a mistake to focus on the language design when we have yet to find an example that clearly demonstrates a good reason to improve it. It is okay —and a Good Thing™— to want to make our own tools nicer and prettier. Just get the rounds properly chambered before you start lining up the ducks.
$0.03