Namespaces
Variants

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

Von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z. B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Erzeugungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum-/Maximumoperationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
Eingeschränkte Algorithmen
Alle Namen in diesem Menü gehören zum Namensraum std::ranges
Nicht modifizierende Sequenzoperationen
Modifizierende Sequenzoperationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen (auf sortierten Bereichen)
       
       
Mengenoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum-/Maximumoperationen
       
       
Permutationsoperationen
Faltungsoperationen
Operationen auf nicht initialisiertem Speicher
Rückgabetypen
 
Definiert in Header <algorithm>
Aufrufsignatur
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 [first, last) oder r um n Positionen. Das Verhalten ist undefiniert, wenn [first, last) kein gültiger Bereich ist.

1) Verschiebt die Elemente in Richtung des Anfangs des Bereichs:
  • Wenn n == 0 || n >= last - first, hat das keine Auswirkungen.
  • Wenn n < 0, ist das Verhalten undefiniert.
  • Andernfalls wird für jede ganze Zahl i in [0, last - first - n) das Element, das sich ursprünglich an Position first + n + i befindet, an Position first + i verschoben. Die Verschiebungen werden in aufsteigender Reihenfolge von i beginnend bei 0 durchgeführt.
3) Verschiebt die Elemente in Richtung des Endes des Bereichs:
  • Wenn n == 0 || n >= last - first, hat das keine Auswirkungen.
  • Wenn n < 0, ist das Verhalten undefiniert.
  • Andernfalls wird für jede ganze Zahl i in [0, last - first - n) das Element, das sich ursprünglich an Position first + i befindet, an Position first + n + i verschoben. Wenn I das Modell bidirectional_iterator erfüllt, werden die Verschiebungen in absteigender Reihenfolge von i beginnend bei last - first - n - 1 durchgeführt.
2,4) Entspricht (1) bzw. (3), verwendet aber 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 unspezifizierten Zustand belassen.

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als Niebloids bekannt), das heißt:

Parameter

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

Rückgabewert

1,2) { first, /*NEW_LAST*/ } , wobei NEW_LAST das Ende des resultierenden Bereichs ist und äquivalent zu:
  • first + ( last - first - n ) , falls 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 , falls n kleiner als last - first ist;
  • last andernfalls.

Komplexität

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

Hinweise

ranges::shift_left / ranges::shift_right haben auf gängigen Implementierungen eine bessere Effizienz, wenn I das Konzept bidirectional_iterator oder (noch besser) random_access_iterator modelliert.

Implementierungen (z.B. MSVC STL ) können Vektorisierung ermöglichen, wenn der Iteratortyp contiguous_iterator modelliert und das Vertauschen seines Werttyps weder nicht-triviale spezielle Memberfunktionen noch ADL -gefundene swap -Funktionen aufruft.

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

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); // hat keine Wirkung: 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   . . δ ε ζ η .

Siehe auch

verschiebt einen Bereich von Elementen an einen neuen Ort
(Algorithmus-Funktionsobjekt)
verschiebt einen Bereich von Elementen in umgekehrter Reihenfolge an einen neuen Ort
(Algorithmus-Funktionsobjekt)
dreht die Reihenfolge der Elemente in einem Bereich
(Algorithmus-Funktionsobjekt)
verschiebt Elemente in einem Bereich
(Funktionsvorlage)