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<int> v(n);
for(vector<int>::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<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;
}
You'd use it like this:
copy_atmost_n(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
N,
std::back_inserter(v)
);
Now you get M elements, where M is either the number of inputs provided or N, whichever is smaller.
As given in comments, copy_n is unsafe for this job, but you can use copy_if with mutable lambda:
#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>
int main(){
const int N = 10;
std::vector<int> v;
//optionally v.reserve(N);
std::copy_if(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(v),
[count=N] (int) mutable {
return count && count--;
});
return 0;
}
as pointed out in this answer: std::copy n elements or to the end