Suppose I want to read n integers from the standard input stream. Reading:
How to read N integers into a vector?
I find the recommended solution is basically:
template<class InputIt, class Size, class OutputIt>
OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
{
for (Size i = 0; i < count && first != last; ++i)
*result++ = *first++;
return result;
}
auto read_n(std::istream& is, std::size_t n) {
vector<int> result;
// possibly reserve n elements
copy_atmost_n(
std::istream_iterator<int>(is),
std::istream_iterator<int>(),
n,
std::back_inserter(result)
);
return result;
}
I dislike this for the following reasons:
- The use of
copy_atmost_n()is making an assumption regarding how failure to "dereference" thefirstiterator will effectfirst's subsequent value. But this assumed behavior is more idiosyncratic than universally obvious. I'm sure this would confuse lots of developers. - A "staging" variable is needed.
- Repetition of
std::istream_iterator<int>.
Does C++20, and especially ranges, afford us a nicer approach?
Note: It is not absolutely necessary to return an std::vector<int>. Some kind of lazy structure may also be used if it makes things easier.