std::uninitialized_move_n() algorithm
- since C++17
// (1)
template< class InputIt, class Size, class NoThrowForwardIt >
std::pair<InputIt, NoThrowForwardIt>
uninitialized_move_n( InputIt first, Size count, NoThrowForwardIt d_first );
// (2)
template< class ExecutionPolicy, class ForwardIt, class Size, class NoThrowForwardIt >
std::pair<ForwardIt, NoThrowForwardIt>
uninitialized_move_n( ExecutionPolicy&& policy, ForwardIt first, Size count, NoThrowForwardIt d_first );
-
(1) Moves
count
elements from a range beginning atfirst
to an uninitialized memory area beginning atd_first
as if by:for (; n > 0; ++d_first, (void) ++first, --n)
::new (static_cast<void*>(std::addressof(*d_first)))
typename std::iterator_traits<NoThrowForwardIt>::value_type(std::move(*first));cautionIf an exception is thrown during the initialization, some objects in
first
+ [0
,n
) are left in a valid but unspecified state, and the objects already constructed are destroyed in an unspecified order.Undefined BehaviourIfd_first
+ [0
,n
) overlaps withfirst
+ [0
,n
), the behavior is undefined. (since C++20) -
(2) Same as (1), but executed according to
policy
.
These overloads participate in overload resolution only if
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>
(until C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>
(since C++20) is true
.
Parameters
first | The beginning of the range of the elements to move. |
d_first | The beginning of the destination range. |
count | Number of elements to move. |
policy | The execution policy to use. See execution policy for details. |
Type requirements
InputIt | LegacyInputIterator |
ForwardIt NoThrowForwardIt | LegacyForwardIterator |
No increment, assignment, comparison, or indirection through valid instances of NoThrowForwardIt
may throw exceptions.
Return value
A pair whose first element is an iterator to the element past the last element moved in the source range, and whose second element is an iterator to the element past the last element moved in the destination range.
Complexity
Linear in count
.
Exceptions
The overloads with a template parameter named ExecutionPolicy
report errors as follows:
- If execution of a function invoked as part of the algorithm throws an exception and
ExecutionPolicy
is one of the standard policies,std::terminate
is called. For none otherExecutionPolicy
, the behavior is implementation-defined. - If the algorithm fails to allocate memory,
std::bad_alloc
is thrown.
Possible implementation
uninitialized_move_n(1)
template<class InputIt, class Size, class NoThrowForwardIt>
std::pair<InputIt, NoThrowForwardIt>
uninitialized_move_n(InputIt first, Size count, NoThrowForwardIt d_first)
{
using Value = typename std::iterator_traits<NoThrowForwardIt>::value_type;
NoThrowForwardIt current = d_first;
try
{
for (; count > 0; ++first, (void) ++current, --count)
::new (static_cast<void*>(std::addressof(*current))) Value(std::move(*first));
}
catch (...)
{
std::destroy(d_first, current);
throw;
}
return {first, current};
}
Examples
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
void print(auto rem, auto first, auto last)
{
for (std::cout << rem; first != last; ++first)
std::cout << std::quoted(*first) << ' ';
std::cout << '\n';
}
int main()
{
std::string in[]{"One", "Definition", "Rule"};
print("initially, in: ", std::begin(in), std::end(in));
if (
constexpr auto sz = std::size(in);
void* out = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz))
{
try
{
auto first{static_cast<std::string*>(out)};
auto last{first + sz};
std::uninitialized_move_n(std::begin(in), sz, first);
print("after move, in: ", std::begin(in), std::end(in));
print("after move, out: ", first, last);
std::destroy(first, last);
}
catch (...)
{
std::cout << "Exception!\n";
}
std::free(out);
}
}
initially, in: "One" "Definition" "Rule"
after move, in: "" "" ""
after move, out: "One" "Definition" "Rule"
Hover to see the original license.