std::ranges::copy_n, std::ranges::copy_n_result
| Defined in header <algorithm>
|
||
| Call signature |
||
template< std::input_iterator I, std::weakly_incrementable O >
requires std::indirectly_copyable<I, O>
constexpr ranges::copy_n_result<I, O>
copy_n( I first, std::iter_difference_t<I> count, O d_first );
|
(1) | (since C++20) |
template< /*execution-policy*/ Ep, std::random_access_iterator I,
std::random_access_iterator O, std::sized_sentinel_for<O> OutS >
requires std::indirectly_copyable<I, O>
ranges::copy_n_result<I, O>
copy_n( Ep&& policy, I first, iter_difference_t<I> count,
O d_first, OutS d_last );
|
(2) | (since C++26) |
| Helper type |
||
template< class I, class O >
using copy_n_result = ranges::in_out_result<I, O>;
|
(3) | (since C++20) |
For the definition of /*execution-policy*/, see this page.
If count is positive, copies the elements in the source range [first, ranges::next(first, count)) to the destination range. Otherwise do nothing.
[d_first, ranges::next(d_first, count)).policy, and the destination range is [d_first, d_last). If the destination range is exhausted before reaching the end of the source range, the remaining elements in the source range will not be copied.The function-like entities described on this page are algorithm function objects (informally known as niebloids), that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
Parameters
| first | - | the beginning of the source range |
| count | - | number of the elements to copy |
| d_first | - | the beginning of the destination range |
| policy | - | the execution policy to use |
Return value
A ranges::copy_n_result object where:
- The data member in holds an iterator past the last copied element in the source range, or an iterator to the beginning of the source range if no element is copied.
- The data member out holds an iterator past the last copy-assigned element in the destination range, or
d_firstif no element is copied.
Complexity
Given
- N1 as max(count,0), and
- N2 as
ranges::distance(d_first, d_last):
Exceptions
- If the temporary memory resources required for parallelization are not available, std::bad_alloc is thrown.
- If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for standard policies, std::terminate is invoked).
Notes
In practice, implementations of ranges::copy_n may avoid multiple assignments and use bulk copy functions such as std::memmove if the value type is TriviallyCopyable and the iterator types satisfy contiguous_iterator. Alternatively, such copy acceleration can be injected during an optimization phase of a compiler.
When copying overlapping ranges, ranges::copy_n is appropriate when copying to the left (beginning of the destination range is outside the source range) while ranges::copy_backward is appropriate when copying to the right (end of the destination range is outside the source range).
Possible implementation
struct copy_n_fn
{
template<std::input_iterator I, std::weakly_incrementable O>
requires std::indirectly_copyable<I, O>
constexpr ranges::copy_n_result<I, O>
operator()(I first, std::iter_difference_t<I> n, O d_first) const
{
for (; n-- > 0; (void)++first, (void)++d_first)
*d_first = *first;
return {std::move(first), std::move(d_first)};
}
};
inline constexpr copy_n_fn copy_n{};
|
Example
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>
#include <string_view>
int main()
{
const std::string_view in{"ABCDEFGH"};
std::string out;
std::ranges::copy_n(in.begin(), 4, std::back_inserter(out));
std::cout << std::quoted(out) << '\n';
out = "abcdefgh";
const auto res{std::ranges::copy_n(in.begin(), 5, out.begin())};
const auto i{std::distance(std::begin(in), res.in)};
const auto j{std::distance(std::begin(out), res.out)};
std::cout << "in[" << i << "] = '" << in[i] << "'\n"
<< "out[" << j << "] = '" << out[j] << "'\n";
}
Output:
"ABCD"
in[5] = 'F'
out[5] = 'f'
