Namespaces
Variants

std::ranges:: advance

From cppreference.net
Iterator library
Iterator concepts
Iterator primitives
Algorithm concepts and utilities
Indirect callable concepts
Common algorithm requirements
(C++20)
(C++20)
(C++20)
Utilities
(C++20)
Iterator adaptors
Range access
(C++11) (C++14)
(C++14) (C++14)
(C++11) (C++14)
(C++14) (C++14)
(C++17) (C++20)
(C++17)
(C++17)
Défini dans l'en-tête <iterator>
Signature d'appel
template < std:: input_or_output_iterator I >
constexpr void advance ( I & i, std:: iter_difference_t < I > n ) ;
(1) (depuis C++20)
template < std:: input_or_output_iterator I, std:: sentinel_for < I > S >
constexpr void advance ( I & i, S bound ) ;
(2) (depuis 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) (depuis C++20)
1) Incrémente l'itérateur donné i pour n fois.
2) Incrémente l'itérateur donné i jusqu'à ce que i == bound .
3) Incrémente l'itérateur donné i pour n fois, ou jusqu'à ce que i == bound , selon la première éventualité.

Si n est négatif, l'itérateur est décrémenté. Dans ce cas, I doit modéliser std::bidirectional_iterator , et S doit être du même type que I si bound est fourni, sinon le comportement est indéfini.

Les entités de type fonction décrites sur cette page sont des objets fonction d'algorithmes (informellement appelés niebloids ), c'est-à-dire :

Table des matières

Paramètres

i - itérateur à avancer
bound - sentinelle désignant la fin de la plage i est un itérateur vers
n - nombre d'incrémentations maximales de i

Valeur de retour

3) La différence entre n et la distance réelle i parcourue.

Complexité

Linéaire.

Cependant, si I modélise également std::random_access_iterator , ou si S modélise std:: sized_sentinel_for < I > , ou si I et S modélisent std:: assignable_from < I & , S > , la complexité est constante.

Notes

Le comportement est indéfini si la séquence spécifiée d'incréments ou de décréments nécessiterait qu'un itérateur non incrémentable (tel que l'itérateur past-the-end) soit incrémenté, ou qu'un itérateur non décrémentable (tel que l'itérateur front ou l'itérateur singulier) soit décrémenté.

Implémentation possible

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 n'est pas constexpr avant 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();

Exemple

#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) valeur : " << *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) valeur : " << *vi << '\n';
    std::cout << "4) diff : " << std::ranges::advance(vi, 2, v.end())
              << ", valeur : " << *vi << '\n';
    std::cout << "5) diff : " << std::ranges::advance(vi, 4, v.end())
              << ", vi == v.end() : " << (vi == v.end()) << '\n';
}

Sortie :

1) valeur : 4
2) vi == v.end() : true
3) valeur : 3
4) diff : 0, valeur : 4
5) diff : 3, vi == v.end() : true

Voir aussi

incrémente un itérateur d'une distance donnée ou jusqu'à une limite
(objet fonction algorithme)
décrémente un itérateur d'une distance donnée ou jusqu'à une limite
(objet fonction algorithme)
retourne la distance entre un itérateur et un sentinelle, ou entre le début et la fin d'une plage
(objet fonction algorithme)
avance un itérateur d'une distance donnée
(modèle de fonction)