◐ Shell
clean mode source ↗

std::ranges::move_backward, std::ranges::move_backward_result - cppreference.com

De cppreference.com

Definido en el archivo de encabezado <algorithm>

Signatura de la llamada

template< std::bidirectional_iterator I1, std::sentinel_for<I1> S1, std::bidirectional_iterator I2 > requires std::indirectly_movable<I1, I2> constexpr move_backward_result<I1, I2> move_backward( I1 first, S1 last, I2 result );

(1) (desde C++20)

template< ranges::bidirectional_range R, std::bidirectional_iterator I > requires std::indirectly_movable<ranges::iterator_t<R>, I> constexpr move_backward_result<ranges::borrowed_iterator_t<R>, I> move_backward( R&& r, I result );

(2) (desde C++20)

Tipos auxiliares

template< class I, class O > using move_backward_result = ranges::in_out_result<I, O>;

(3) (desde C++20)

1) Mueve los elementos en el rango definido por [firstlast), a otro rango [result - Nresult), donde N = ranges::distance(first, last). Los elementos se mueven en orden inverso (el último elemento se mueve primero), pero se conserva su orden relativo. El comportamiento no está definido si result está dentro de (first, last]. En tal caso, ranges::move puede usarse en su lugar.

2) Igual que (1), pero usa r como rango fuente, como si usara ranges::begin(r) como {{c|first} }, y ranges::end(r) como last.

Los elementos en el rango desde el que se movió aún contendrán valores válidos del tipo apropiado, pero no necesariamente los mismos valores que antes del movimiento, como si usara *(result - n) = ranges::iter_move(last - n) para cada entero n, donde 0 n < N.

Las entidades similares a funciones descritas en esta página son niebloids, es decir:

En la práctica, pueden implementarse como objetos función o con extensiones de compilador especiales.

Parámetros

first - El comienzo del rango de los elementos a mover.
last - El final del rango de los elementos a mover.
r - El rango de los elementos a mover.
result - El final del rango de destino.

Valor de retorno

{last, result - N}.

Complejidad

1) Exactamente N asignaciones por movimiento.

2) Exactamente ranges::distance(r) asignaciones por movimiento.

Notas

Al mover rangos superpuestos, ranges::move es apropiado cuando se mueve hacia la izquierda (el comienzo del rango de destino está fuera del rango de origen) mientras que ranges::move_backward es apropiado cuando se mueve hacia la derecha (el final del rango de destino está fuera del rango de origen).

Posible implementación

struct move_backward_fn
{
    template<std::bidirectional_iterator I1, std::sentinel_for<I1> S1,
             std::bidirectional_iterator I2>
    requires std::indirectly_movable<I1, I2>
    constexpr ranges::move_backward_result<I1, I2>
        operator()(I1 first, S1 last, I2 result) const
    {
        auto i {last};
        for (; i != first; *--result = ranges::iter_move(--i))
        {}
        return {std::move(last), std::move(result)};
    }

    template<ranges::bidirectional_range R, std::bidirectional_iterator I>
    requires std::indirectly_movable<ranges::iterator_t<R>, I>
    constexpr ranges::move_backward_result<ranges::borrowed_iterator_t<R>, I>
        operator()(R&& r, I result) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), std::move(result));
    }
};

inline constexpr move_backward_fn move_backward {};

Ejemplo

#include <algorithm>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>

using Vec = std::vector<std::string>;

void print(std::string_view rem, Vec const& vec)
{
    std::cout << rem << "[" << vec.size() << "]: ";
    for (const std::string& s : vec)
        std::cout << (s.size() ? s : std::string{"·"}) << ' ';
    std::cout << '\n';
}

int main()
{
    Vec a{"▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"};
    Vec b(a.size());

    print("Before move:\n" "a", a);
    print("b", b);

    std::ranges::move_backward(a, b.end());

    print("\n" "Move a >> b:\n" "a", a);
    print("b", b);

    std::ranges::move_backward(b.begin(), b.end(), a.end());
    print("\n" "Move b >> a:\n" "a", a);
    print("b", b);

    std::ranges::move_backward(a.begin(), a.begin()+3, a.end());
    print("\n" "Overlapping move a[0, 3) >> a[5, 8):\n" "a", a);
}

Posible salida:

Before move:
a[8]: ▁ ▂ ▃ ▄ ▅ ▆ ▇ █
b[8]: · · · · · · · ·

Move a >> b:
a[8]: · · · · · · · ·
b[8]: ▁ ▂ ▃ ▄ ▅ ▆ ▇ █

Move b >> a:
a[8]: ▁ ▂ ▃ ▄ ▅ ▆ ▇ █
b[8]: · · · · · · · ·

Overlapping move a[0, 3) >> a[5, 8):
a[8]: · · · ▄ ▅ ▁ ▂ ▃

Véase también