'Why do C++ istreams only allow formatted-reading into an existing variable?
In C++ (and using the standard library facilities), if I want to read an integer from the standard input, I need to do this:
int x;
std::cin >> x;
And looking at the std::istream page on cppreference, it seems there is no function such as std::cin.scan<int>() which returns an int prvalue; nor is there a freestanding function std::scan<int>(std::cin) which does so.
My question is: Why?
It seems nonsensical to me to encourage people to:
- Define and name variables they may not need (e.g. as opposed to
func_taking_an_int(std::cin.scan<int>()). - Split the definition and the initialization of a variable
So what's the rationale of only supporting the operator form?
Now, I know C++ istreams go back decades, but it's still weird to me (not to mention that an extra method/function could have been added later on).
Motivation: I saw this question and realized that, to our shame, we cannot offer the poster a better way to write their program other than using an uninitialized variable. I was assuming that, surely, we can help that poster bring the definition into the same statement as the initialization... but it seems we cannot.
Solution 1:[1]
Of course there is one:
#include <iostream>
#include <iterator>
int main() {
auto const i = *std::istream_iterator<int>(std::cin);
}
Note that this causes UB if std::cin doesn't have a valid int. You might expect it to throw an exception, but since iostreams predate exceptions, that is not how the API works. You should compare it with the end-iterator.
std::istream_iterator<int> it(std::cin), end;
auto const i = (it != end) ? *it : -1;
Finally, you might want to wrap that in a nice, reusable API:
#include <iostream>
#include <iterator>
#include <optional>
template <class T>
auto scan(std::istream& is) -> std::optional<T> {
std::istream_iterator<int> it(std::cin), end;
if (it != end) return std::optional(*it);
return std::nullopt;
}
int main() {
auto const i = scan<int>(std::cin);
if (i) {
return *i;
}
return -1;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
