std::ranges::advance
| Definiert in Header <iterator> |
||
| Aufruf-Signatur |
||
| template< std::input_or_output_iterator I > constexpr void advance( I& i, std::iter_difference_t<I> n ); |
(1) | (seit C++20) |
| template< std::input_or_output_iterator I, std::sentinel_for<I> S > constexpr void advance( I& i, S bound ); |
(2) | (seit C++20) |
| template< std::input_or_output_iterator I, std::sentinel_for<I> S > constexpr std::iter_difference_t<I> advance( I& i, std::iter_difference_t<I> n, S bound ); |
(3) | (seit C++20) |
Wenn n negativ ist, wird der Iterator dekrementiert. In diesem Fall muss I std::bidirectional_iterator modellieren und S muss vom gleichen Typ wie I sein, wenn bound angegeben ist, andernfalls ist das Verhalten undefiniert.
Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als niebloids bekannt), d.h.
- Können explizite Template-Argumentlisten bei keinem von ihnen angegeben werden.
- Keiner von ihnen ist für Argument-abhängige Suche sichtbar.
- Wenn einer von ihnen durch normale unqualifizierte Suche als Name links vom Funktionsaufrufoperator gefunden wird, wird die Argument-abhängige Suche unterdrückt.
Inhalt |
[edit] Parameter
| i | - | Der zu verschiebende Iterator |
| bound | - | Sentinel, der das Ende des Bereichs bezeichnet, auf den i ein Iterator ist |
| n | - | Maximale Anzahl von Inkrementierungen von i |
[edit] Rückgabewert
[edit] Komplexität
Linear.
Wenn I zusätzlich std::random_access_iterator modelliert oder S std::sized_sentinel_for<I> modelliert oder I und S std::assignable_from<I&, S> modellieren, ist die Komplexität konstant.
[edit] Hinweise
Das Verhalten ist undefiniert, wenn die angegebene Sequenz von Inkrementierungen oder Dekrementierungen erfordert, dass ein nicht inkrementierbarer Iterator (wie z. B. ein Iterator hinter dem Ende) inkrementiert wird, oder dass ein nicht dekrementierbarer Iterator (wie z. B. ein Iterator am Anfang oder ein singulärer Iterator) dekrementiert wird.
[edit] Mögliche Implementierung
struct advance_fn { template<std::input_or_output_iterator I> constexpr void operator()(I& i, std::iter_difference_t<I> n) const { if constexpr (std::random_access_iterator<I>) i += n; else { while (n > 0) { --n; ++i; } if constexpr (std::bidirectional_iterator<I>) { while (n < 0) { ++n; --i; } } } } template<std::input_or_output_iterator I, std::sentinel_for<I> S> constexpr void operator()(I& i, S bound) const { if constexpr (std::assignable_from<I&, S>) i = std::move(bound); else if constexpr (std::sized_sentinel_for<S, I>) (*this)(i, bound - i); else while (i != bound) ++i; } template<std::input_or_output_iterator I, std::sentinel_for<I> S> constexpr std::iter_difference_t<I> operator()(I& i, std::iter_difference_t<I> n, S bound) const { if constexpr (std::sized_sentinel_for<S, I>) { // std::abs is not constexpr until C++23 auto abs = [](const std::iter_difference_t<I> x) { return x < 0 ? -x : x; }; if (const auto dist = abs(n) - abs(bound - i); dist < 0) { (*this)(i, bound); return -dist; } (*this)(i, n); return 0; } else { while (n > 0 && i != bound) { --n; ++i; } if constexpr (std::bidirectional_iterator<I>) { while (n < 0 && i != bound) { ++n; --i; } } return n; } } }; inline constexpr auto advance = advance_fn(); |
[edit] Beispiel
#include <iostream> #include <iterator> #include <vector> int main() { std::vector<int> v {3, 1, 4}; auto vi = v.begin(); std::ranges::advance(vi, 2); std::cout << "1) value: " << *vi << '\n' << std::boolalpha; std::ranges::advance(vi, v.end()); std::cout << "2) vi == v.end(): " << (vi == v.end()) << '\n'; std::ranges::advance(vi, -3); std::cout << "3) value: " << *vi << '\n'; std::cout << "4) diff: " << std::ranges::advance(vi, 2, v.end()) << ", value: " << *vi << '\n'; std::cout << "5) diff: " << std::ranges::advance(vi, 4, v.end()) << ", vi == v.end(): " << (vi == v.end()) << '\n'; }
Ausgabe
1) value: 4 2) vi == v.end(): true 3) value: 3 4) diff: 0, value: 4 5) diff: 3, vi == v.end(): true
[edit] Siehe auch
| (C++20) |
inkrementiert einen Iterator um eine gegebene Distanz oder zu einer Grenze (Algorithmus-Funktionsobjekt) |
| (C++20) |
dekrementiert einen Iterator um eine gegebene Distanz oder zu einer Grenze (Algorithmus-Funktionsobjekt) |
| (C++20) |
gibt die Distanz zwischen einem Iterator und einem Sentinel zurück oder die Distanz zwischen dem Anfang und dem Ende eines Bereichs (Algorithmus-Funktionsobjekt) |
| bewegt einen Iterator um die angegebene Distanz vorwärts (Funktionsvorlage) |