Skip to main content

std::ranges::uninitialized_move() algorithm

// (1)
uninitialized_move_result<I, O>
uninitialized_move( I ifirst, S1 ilast, O ofirst, S2 olast );

// (2)
uninitialized_move_result< ranges::borrowed_iterator_t<IR>,
ranges::borrowed_iterator_t<OR> >
uninitialized_move( IR&& in_range, OR&& out_range );

The type of arguments are generic and have following constraints:

Additionally, each overload has the following constraints:

  • (1) std::constructible_from< std::iter_value_t<O>, std::iter_rvalue_reference_t<I> >
  • (1) std::constructible_from< ranges::range_value_t<OR>, ranges::range_rvalue_reference_t<IR> >

With the helper types defined as follows:

template< class I, class O >
using uninitialized_move_result = ranges::in_out_result<I, O>;
  • (1) Moves N elements from the input range [ifirst; ilast) to the output range [ofirst; olast), where N is min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast)).

    The function has the effect equal to:

    for (; ifirst != ilast && ofirst != olast; ++ofirst, ++ifirst)
    ::new (static_cast<void*>(std::addressof(*first)))
    std::remove_reference_t<std::iter_reference_t<O>>(ranges::iter_move(ifirst));
    caution

    If an exception is thrown during the initialization then the objects that already constructed in [ofirst; olast) are destroyed in an unspecified order.

    Also, the objects in [ifirst; ilast) that were already moved, are left in a valid but unspecified state.

  • (2) Same as (1), but uses in_range as the first range and out_range as the second range, as if using ranges::begin(in_range) as ifirst, ranges::end(in_range) as ilast, ranges::begin(out_range) as ofirst, and ranges::end(out_range) as olast.

The function-like entities described on this page are niebloids.

Parameters

ifirst
ilast

The input range to move elements from.

in_range

The input range to move elements from.

ofirst
olast

The destination range to initialize.

out_range

The destination range to initialize.

Return value

{
ifirst + N,
ofirst + N
}

Complexity

Linear in N.

Exceptions

The exception thrown on construction of the elements in the destination range, if any.

Possible implementation

uninitialized_move(1) and uninitialized_move(2)
struct uninitialized_move_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_rvalue_reference_t<I>>
ranges::uninitialized_move_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)
::new (const_cast<void*>(static_cast<const volatile void*>
(std::addressof(*current)))) std::remove_reference_t<
std::iter_reference_t<O>>(ranges::iter_move(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_rvalue_reference_t<IR>>
ranges::uninitialized_move_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_move_fn uninitialized_move{};

Notes

An implementation may improve the efficiency of ranges::uninitialized_move if the value type of the output range is TrivialType.

Examples

Main.cpp
#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[]{"Home", "World"};
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::ranges::uninitialized_move(std::begin(in), std::end(in), first, last);

print("after move, in: ", std::begin(in), std::end(in));
print("after move, out: ", first, last);

std::ranges::destroy(first, last);
}
catch (...)
{
std::cout << "Exception!\n";
}
std::free(out);
}
}
Output
initially, in: "Home" "World"
after move, in: "" ""
after move, out: "Home" "World"
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::ranges::uninitialized_move() algorithm

// (1)
uninitialized_move_result<I, O>
uninitialized_move( I ifirst, S1 ilast, O ofirst, S2 olast );

// (2)
uninitialized_move_result< ranges::borrowed_iterator_t<IR>,
ranges::borrowed_iterator_t<OR> >
uninitialized_move( IR&& in_range, OR&& out_range );

The type of arguments are generic and have following constraints:

Additionally, each overload has the following constraints:

  • (1) std::constructible_from< std::iter_value_t<O>, std::iter_rvalue_reference_t<I> >
  • (1) std::constructible_from< ranges::range_value_t<OR>, ranges::range_rvalue_reference_t<IR> >

With the helper types defined as follows:

template< class I, class O >
using uninitialized_move_result = ranges::in_out_result<I, O>;
  • (1) Moves N elements from the input range [ifirst; ilast) to the output range [ofirst; olast), where N is min(ranges::distance(ifirst, ilast), ranges::distance(ofirst, olast)).

    The function has the effect equal to:

    for (; ifirst != ilast && ofirst != olast; ++ofirst, ++ifirst)
    ::new (static_cast<void*>(std::addressof(*first)))
    std::remove_reference_t<std::iter_reference_t<O>>(ranges::iter_move(ifirst));
    caution

    If an exception is thrown during the initialization then the objects that already constructed in [ofirst; olast) are destroyed in an unspecified order.

    Also, the objects in [ifirst; ilast) that were already moved, are left in a valid but unspecified state.

  • (2) Same as (1), but uses in_range as the first range and out_range as the second range, as if using ranges::begin(in_range) as ifirst, ranges::end(in_range) as ilast, ranges::begin(out_range) as ofirst, and ranges::end(out_range) as olast.

The function-like entities described on this page are niebloids.

Parameters

ifirst
ilast

The input range to move elements from.

in_range

The input range to move elements from.

ofirst
olast

The destination range to initialize.

out_range

The destination range to initialize.

Return value

{
ifirst + N,
ofirst + N
}

Complexity

Linear in N.

Exceptions

The exception thrown on construction of the elements in the destination range, if any.

Possible implementation

uninitialized_move(1) and uninitialized_move(2)
struct uninitialized_move_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_rvalue_reference_t<I>>
ranges::uninitialized_move_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)
::new (const_cast<void*>(static_cast<const volatile void*>
(std::addressof(*current)))) std::remove_reference_t<
std::iter_reference_t<O>>(ranges::iter_move(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_rvalue_reference_t<IR>>
ranges::uninitialized_move_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_move_fn uninitialized_move{};

Notes

An implementation may improve the efficiency of ranges::uninitialized_move if the value type of the output range is TrivialType.

Examples

Main.cpp
#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[]{"Home", "World"};
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::ranges::uninitialized_move(std::begin(in), std::end(in), first, last);

print("after move, in: ", std::begin(in), std::end(in));
print("after move, out: ", first, last);

std::ranges::destroy(first, last);
}
catch (...)
{
std::cout << "Exception!\n";
}
std::free(out);
}
}
Output
initially, in: "Home" "World"
after move, in: "" ""
after move, out: "Home" "World"
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.