Namensräume
Varianten
Aktionen

std::ranges::advance

Von cppreference.com
< cpp‎ | iterator
 
 
Iterator-Bibliothek
Iterator-Konzepte
Iterator-Primitive
Algorithmus-Konzepte und Hilfsprogramme
Indirekte aufrufbare Konzepte
Gemeinsame Algorithmus-Anforderungen
(C++20)
(C++20)
(C++20)
Dienstprogramme
(C++20)
Iterator-Adapter
Iterator-Operationen
(C++11)  
(C++11)
ranges::advance
(C++20)
Bereichszugriff
(C++11)(C++14)
(C++14)(C++14)  
(C++11)(C++14)
(C++14)(C++14)  
(C++17)(C++20)
(C++17)
(C++17)
 
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)
1) Inkrementiert den gegebenen Iterator i für n mal.
2) Inkrementiert den gegebenen Iterator i, bis i == bound.
3) Inkrementiert den gegebenen Iterator i für n mal oder bis i == bound, je nachdem, was zuerst eintritt.

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.

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

3) Die Differenz zwischen n und dem tatsächlich zurückgelegten Abstand von i.

[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

inkrementiert einen Iterator um eine gegebene Distanz oder zu einer Grenze
(Algorithmus-Funktionsobjekt)[bearbeiten]
dekrementiert einen Iterator um eine gegebene Distanz oder zu einer Grenze
(Algorithmus-Funktionsobjekt)[bearbeiten]
gibt die Distanz zwischen einem Iterator und einem Sentinel zurück oder die Distanz zwischen dem Anfang und dem Ende eines Bereichs
(Algorithmus-Funktionsobjekt)[bearbeiten]
bewegt einen Iterator um die angegebene Distanz vorwärts
(Funktionsvorlage) [bearbeiten]