std::ranges:: shift_left, std::ranges:: shift_right
|
Definiert im Header
<algorithm>
|
||
|
Aufrufsignatur
|
||
|
template
<
std::
permutable
I,
std::
sentinel_for
<
I
>
S
>
constexpr
ranges::
subrange
<
I
>
|
(1) | (seit C++23) |
|
template
<
ranges::
forward_range
R
>
requires
std::
permutable
<
ranges::
iterator_t
<
R
>>
|
(2) | (seit C++23) |
|
template
<
std::
permutable
I,
std::
sentinel_for
<
I
>
S
>
constexpr
ranges::
subrange
<
I
>
|
(3) | (seit C++23) |
|
template
<
ranges::
forward_range
R
>
requires
std::
permutable
<
ranges::
iterator_t
<
R
>>
|
(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.
- Wenn n == 0 || n >= last - first , gibt es keine Effekte.
- Wenn n < 0 , ist das Verhalten undefiniert.
-
Andernfalls wird für jede Ganzzahl
iin[ 0 ,last - first - n)das Element, das ursprünglich an Position first + n + i stand, an Position first + i verschoben. Die Verschiebungen werden in aufsteigender Reihenfolge vonibeginnend bei 0 durchgeführt.
- Wenn n == 0 || n >= last - first , gibt es keine Effekte.
- Wenn n < 0 , ist das Verhalten undefiniert.
-
Andernfalls wird für jede ganze Zahl
iin[ 0 ,last - first - n)das Element, das ursprünglich an Position first + i stand, an Position first + n + i verschoben. FallsIdas Konzeptbidirectional_iteratormodelliert, werden die Verschiebungen in absteigender Reihenfolge vonibeginnend bei last - first - n - 1 durchgeführt.
Elemente, die sich im ursprünglichen Bereich befinden, aber nicht im neuen Bereich, verbleiben in einem gültigen, aber nicht spezifizierten Zustand.
Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithm Function Objects (informell bekannt als Niebloids ), das heißt:
- Explizite Template-Argumentlisten können beim Aufruf keiner von ihnen angegeben werden.
- Keiner von ihnen ist sichtbar für argument-dependent lookup .
- Wenn einer von ihnen durch normal unqualified lookup als Name links vom Funktionsaufrufoperator gefunden wird, wird argument-dependent lookup unterdrückt.
Inhaltsverzeichnis |
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
NEW_LAST
das Ende des resultierenden Bereichs ist und äquivalent zu:
-
first
+
(
last
-
first
-
n
)
, falls
nkleiner ist als last - first ; - first andernfalls.
NEW_FIRST
der Anfang des resultierenden Bereichs ist und äquivalent zu:
-
first
+
n
, falls
nkleiner als last - first ist; - last andernfalls.
Komplexität
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
|
(C++20)
|
verschiebt eine Reihe von Elementen an einen neuen Speicherort
(Algorithmus-Funktionsobjekt) |
|
(C++20)
|
verschiebt eine Reihe von Elementen in umgekehrter Reihenfolge an einen neuen Speicherort
(Algorithmus-Funktionsobjekt) |
|
(C++20)
|
rotiert die Reihenfolge der Elemente in einem Bereich
(Algorithmus-Funktionsobjekt) |
|
(C++20)
|
verschiebt Elemente in einem Bereich
(Funktions-Template) |