Namensräume
Varianten
Aktionen

std::ranges::shift_left, std::ranges::shift_right

Von cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
Operationen auf uninitialisiertem Speicher
 
Eingeschränkte Algorithmen
Alle Namen in diesem Menü gehören zum Namespace std::ranges
Nicht-modifizierende Sequenzoperationen
Modifizierende Sequenzoperationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen (auf sortierten Bereichen)
       
       
Mengenoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
       
       
Permutationsoperationen
Faltoperationen
Operationen auf uninitialisiertem Speicher
Rückgabetypen
 
Definiert in Header <algorithm>
Aufruf-Signatur
template< std::permutable I, std::sentinel_for<I> S >

constexpr ranges::subrange<I>

    shift_left( I first, S last, std::iter_difference_t<I> n );
(1) (seit C++23)
template< ranges::forward_range R >

requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>

    shift_left( R&& r, ranges::range_difference_t<R> n );
(2) (seit C++23)
template< std::permutable I, std::sentinel_for<I> S >

constexpr ranges::subrange<I>

    shift_right( I first, S last, std::iter_difference_t<I> n );
(3) (seit C++23)
template< ranges::forward_range R >

requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>

    shift_right( R&& r, ranges::range_difference_t<R> n );
(4) (seit C++23)

Verschiebt die Elemente im Bereich [firstlast) oder r um n Positionen. Das Verhalten ist undefiniert, wenn [firstlast) kein gültiger Bereich ist.

1) Verschiebt die Elemente in Richtung des Bereichsanfangs
  • Wenn n == 0 || n >= last - first, gibt es keine Effekte.
  • Wenn n < 0, ist das Verhalten undefiniert.
  • Andernfalls, für jede ganze Zahl i in [0last - first - n), wird das Element, das sich ursprünglich an Position first + n + i befand, an Position first + i verschoben. Die Verschiebungen erfolgen in aufsteigender Reihenfolge von i, beginnend bei 0.
3) Verschiebt die Elemente in Richtung des Bereichsendes
  • Wenn n == 0 || n >= last - first, gibt es keine Effekte.
  • Wenn n < 0, ist das Verhalten undefiniert.
  • Andernfalls, für jede ganze Zahl i in [0last - first - n), wird das Element, das sich ursprünglich an Position first + i befand, an Position first + n + i verschoben. Wenn I bidirectional_iterator modelliert, dann erfolgen die Verschiebungen in absteigender Reihenfolge von i, beginnend bei last - first - n - 1.
2,4) Wie in (1) oder (3), aber verwendet r als Bereich, als ob ranges::begin(r) als first und ranges::end(r) als last verwendet würden.

Elemente, die sich im ursprünglichen Bereich befinden, aber nicht im neuen Bereich, werden in einem gültigen, aber nicht spezifizierten Zustand belassen.

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als niebloids bekannt), d.h.

Inhalt

[bearbeiten] Parameter

first, last - das Iterator-Sentinel-Paar, das den Bereich der zu verschiebenden Elemente definiert
r - der zu verschiebende Bereich von Elementen
n - die Anzahl der zu verschiebenden Positionen

[bearbeiten] Rückgabewert

1,2) {first, /*NEW_LAST*/}, wobei NEW_LAST das Ende des resultierenden Bereichs ist und äquivalent zu
  • first + (last - first - n), wenn n kleiner ist als last - first;
  • first andernfalls.
3,4) {/*NEW_FIRST*/, last}, wobei NEW_FIRST der Anfang des resultierenden Bereichs ist und äquivalent zu
  • first + n, wenn n kleiner ist als last - first;
  • last andernfalls.

[bearbeiten] Komplexität

1,2) Höchstens ranges::distance(first, last) - n Zuweisungen.
3,4) Höchstens ranges::distance(first, last) - n Zuweisungen oder Tausche.

[bearbeiten] Hinweise

ranges::shift_left / ranges::shift_right hat eine bessere Effizienz bei gängigen Implementierungen, wenn I bidirectional_iterator oder (besser) random_access_iterator modelliert.

Implementierungen (z. B. MSVC STL) können Vektorisierung aktivieren, wenn der Iteratortyp contiguous_iterator modelliert und das Tauschen seines Werttyps weder eine nicht-triviale spezielle Memberfunktion noch eine ADL-gefundene swap aufruft.

Feature-Test-Makro Wert Std Feature
__cpp_lib_shift 202202L (C++23) std::ranges::shift_left und std::ranges::shift_right

[bearbeiten] Beispiel

#include <algorithm>
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
 
struct S
{
    int value{0};
    bool specified_state{true};
 
    S(int v = 0) : value{v} {}
    S(S const& rhs) = default;
    S(S&& rhs) { *this = std::move(rhs); }
    S& operator=(S const& rhs) = default;
    S& operator=(S&& rhs)
    {
        if (this != &rhs)
        {
            value = rhs.value;
            specified_state = rhs.specified_state;
            rhs.specified_state = false;
        }
        return *this;
    }
};
 
template<typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
{
    for (const auto& s : v)
    {
        if constexpr (std::is_same_v<T, S>)
            s.specified_state ? os << s.value << ' ' : os << ". ";
        else if constexpr (std::is_same_v<T, std::string>)
            os << (s.empty() ? "." : s) << ' ';
        else
            os << s << ' ';
    }
    return os;
}
 
int main()
{
    std::cout << std::left;
 
    std::vector<S> a{1, 2, 3, 4, 5, 6, 7};
    std::vector<int> b{1, 2, 3, 4, 5, 6, 7};
    std::vector<std::string> c{"α", "β", "γ", "δ", "ε", "ζ", "η"};
 
    std::cout << "vector<S> \tvector<int> \tvector<string>\n";
    std::cout << a << "  " << b << "  " << c << '\n';
 
    std::ranges::shift_left(a, 3);
    std::ranges::shift_left(b, 3);
    std::ranges::shift_left(c, 3);
    std::cout << a << "  " << b << "  " << c << '\n';
 
    std::ranges::shift_right(a, 2);
    std::ranges::shift_right(b, 2);
    std::ranges::shift_right(c, 2);
    std::cout << a << "  " << b << "  " << c << '\n';
 
    std::ranges::shift_left(a, 8); // has no effect: n >= last - first
    std::ranges::shift_left(b, 8); // ditto
    std::ranges::shift_left(c, 8); // ditto
    std::cout << a << "  " << b << "  " << c << '\n';
 
//  std::ranges::shift_left(a, -3); // UB
}

Mögliche Ausgabe

vector<S>       vector<int>     vector<string>
1 2 3 4 5 6 7   1 2 3 4 5 6 7   α β γ δ ε ζ η
4 5 6 7 . . .   4 5 6 7 5 6 7   δ ε ζ η . . .
. . 4 5 6 7 .   4 5 4 5 6 7 5   . . δ ε ζ η .
. . 4 5 6 7 .   4 5 4 5 6 7 5   . . δ ε ζ η .

[bearbeiten] Siehe auch

Verschiebt einen Elementbereich an einen neuen Speicherort
(Algorithmus-Funktionsobjekt)[edit]
Verschiebt einen Elementbereich in umgekehrter Reihenfolge an einen neuen Speicherort
(Algorithmus-Funktionsobjekt)[edit]
Rotiert die Reihenfolge der Elemente in einem Bereich
(Algorithmus-Funktionsobjekt)[edit]
Verschiebt Elemente in einem Bereich
(Funktionstemplate) [edit]