If I want to read all integers from standard input to a vector, I can use the handy:
vector v{istream_iterator(cin), istream_i
You usually shouldn't do this with std::copy_n, which assumes that the provided iterator, when incremented n times, remains valid:
Copies exactly
countvalues from the range beginning atfirstto the range beginning atresult. Formally, for each non-negative integeri < n, performs*(result + i) = *(first + i).(cppreference.com article on std::copy_n)
If you can guarantee that, then fine, but generally with std::cin that's not possible. You can quite easily have it dereferencing an invalid iterator:
The default-constructed
std::istream_iteratoris known as the end-of-stream iterator. When a validstd::istream_iteratorreaches the end of the underlying stream, it becomes equal to the end-of-stream iterator. Dereferencing or incrementing it further invokes undefined behavior.(cppreference.com article on std::istream_iterator)
You're pretty much there with your loop, though I'd probably use stronger termination condition to avoid excess reads from a "dead" stream:
vector v(n);
for(vector::size_type i = 0; i < n; i++)
if (!cin >> v[i])
break;
I'd be tempted actually to wrap this into something that's like std::copy_n, but accepts a full "range" whose bounds may be validated in addition to counting from 0 to N.
An implementation might look like:
template
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;
}
You'd use it like this:
copy_atmost_n(
std::istream_iterator(std::cin),
std::istream_iterator(),
N,
std::back_inserter(v)
);
Now you get M elements, where M is either the number of inputs provided or N, whichever is smaller.