std::ranges::uninitialized_copy() algorithm
- since C++20
- Simplified
- Detailed
// (1)
uninitialized_copy_result<I, O>
uninitialized_copy( I ifirst, S1 ilast, O ofirst, S2 olast );
// (2)
uninitialized_copy_result< ranges::borrowed_iterator_t<IR>,
ranges::borrowed_iterator_t<OR> >
uninitialized_copy( IR&& in_range, OR&& out_range );
The type of arguments are generic and have following constraints:
I
-std::input_iterator
S1
,S2
-std::sentinel_for<I>
,no-throw-sentinel-for<O>
O
-no-throw-forward-iterator
IR
-ranges::input_range
OR
-no-throw-forward-range
Additionally, each overload has the following constraints:
- (1)
std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
- (1)
std::constructible_from<ranges::range_value_t<OR>, ranges::range_reference_t<IR>>
// (1)
template<
std::input_iterator I,
std::sentinel_for<I> S1,
no-throw-forward-iterator O,
no-throw-sentinel-for<O> S2
>
requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
uninitialized_copy_result<I, O>
uninitialized_copy( I ifirst, S1 ilast, O ofirst, S2 olast );
// (2)
template<
ranges::input_range IR,
no-throw-forward-range OR
>
requires std::constructible_from<ranges::range_value_t<OR>,
ranges::range_reference_t<IR>>
uninitialized_copy_result< ranges::borrowed_iterator_t<IR>,
ranges::borrowed_iterator_t<OR> >
uninitialized_copy( IR&& in_range, OR&& out_range );
With the helper types defined as follows:
template< class I, class O >
using uninitialized_copy_result = ranges::in_out_result<I, O>;
-
(1) Let
N
beranges::min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast))
: ConstructsN
elements in the output range [ofirst
;olast
), which is an uninitialized memory area, from the elements in the input range [ifirst
;ilast
).importantThe input and output ranges must not overlap.
cautionIf an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order.
The function has the effect equal to:
for (; !(ifirst == ilast || ofirst == olast); ++ofirst, ++ifirst)
{
::new (static_cast<void*>(std::addressof(*ofirst)))
std::remove_reference_t<std::iter_reference_t<O>>(*ifirst);
} -
(2) Same as (1), but uses
in_range
as the first range andout_range
as the second range, as if usingranges::begin(in_range)
asifirst
,ranges::end(in_range)
asilast
,ranges::begin(out_range)
asofirst
, andranges::end(out_range)
asolast
.
The function-like entities described on this page are niebloids.
Parameters
ifirst ilast | The range of elements to copy from. |
in_range | The range of elements to copy from. |
ofirst olast | The destination range. |
out_range | The destination range. |
Return value
{
ifirst + N,
ofirst + N
}
Complexity
Given N
as ranges::min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast))
:
O(N)
Exceptions
The exception thrown on construction of the elements in the destination range, if any.
Possible implementation
uninitialized_copy(1) and uninitialized_copy(2)
struct uninitialized_copy_fn
{
template<std::input_iterator I, std::sentinel_for<I> S1,
no-throw-forward-iterator O, no-throw-sentinel-for<O> S2>
requires std::constructible_from<std::iter_value_t<O>, std::iter_reference_t<I>>
ranges::uninitialized_copy_result<I, O>
operator()(I ifirst, S1 ilast, O ofirst, S2 olast) const
{
O current{ofirst};
try
{
for (; !(ifirst == ilast or current == olast); ++ifirst, ++current)
ranges::construct_at(std::addressof(*current), *ifirst);
return {std::move(ifirst), std::move(current)};
}
catch (...) // rollback: destroy constructed elements
{
for (; ofirst != current; ++ofirst)
ranges::destroy_at(std::addressof(*ofirst));
throw;
}
}
template<ranges::input_range IR, no-throw-forward-range OR>
requires std::constructible_from<ranges::range_value_t<OR>,
ranges::range_reference_t<IR>>
ranges::uninitialized_copy_result<ranges::borrowed_iterator_t<IR>,
ranges::borrowed_iterator_t<OR>>
operator()(IR&& in_range, OR&& out_range) const
{
return (*this)(ranges::begin(in_range), ranges::end(in_range),
ranges::begin(out_range), ranges::end(out_range));
}
};
inline constexpr uninitialized_copy_fn uninitialized_copy{};
Notes
An implementation may improve the efficiency of ranges::uninitialized_copy
if the value type of the output range is TrivialType
.
Examples
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
int main()
{
const char* v[]{ "This", "is", "an", "example", };
if (const auto sz{std::size(v)};
void* pbuf = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz))
{
try
{
auto first {static_cast<std::string*>(pbuf)};
auto last {first + sz};
std::ranges::uninitialized_copy(std::begin(v), std::end(v), first, last);
std::cout << "{ ";
for (auto it{first}; it != last; ++it)
std::cout << std::quoted(*it) << ", ";
std::cout << "};\n";
std::ranges::destroy(first, last);
}
catch (...)
{
std::cout << "uninitialized_copy exception\n";
}
std::free(pbuf);
}
}
{ "This", "is", "an", "example", };
Hover to see the original license.