std::advance(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… NAME πŸ’…

std::advance β€” the NAME line is literally std::advance - std::advance, and this is the C++ Standard Libary manual page for std::advance(3), bestie. We're doing iterator math, and it's honestly giving main-character energy. πŸ’–


🌸 Synopsis 🌸

Defined in header <iterator>:

template< class InputIt, class Distance >           (until C++17)
void advance( InputIt& it, Distance n );
template< class InputIt, class Distance >           (since C++17)
constexpr void advance( InputIt& it, Distance n );

Increments given iterator it by n elements. ✨

If n is negative, the iterator is decremented. In this case, InputIt must meet the requirements of LegacyBidirectionalIterator, otherwise the behavior is undefined. No cap, that part matters. 🫢


πŸŽ€ Parameters πŸŽ€

  • it β€” iterator to be advanced
  • n β€” number of elements it should be advanced

πŸ¦‹ Type requirements πŸ¦‹

  • InputIt must meet the requirements of LegacyInputIterator.

✨ Return value ✨

(none) β€” literally nothing, bestie. πŸ’…


πŸ”₯ Complexity πŸ”₯

Linear.

However, if InputIt additionally meets the requirements of LegacyRandomAccessIterator, complexity is constant. Slay. ⭐


πŸ’€ Notes πŸ’€

The behavior is undefined if the specified sequence of increments or decrements would require that a non-incrementable iterator (such as the past-the-end iterator) is incremented, or that a non-decrementable iterator (such as the front iterator or the singular iterator) is decremented. 😭 This is the β€œdo not do that” zone.

🧚 Possible implementation 🧚

See also the implementations in libstdc++ and libc++.

🌈 Non-constexpr version 🌈

          namespace detail
          {
              template<class It>
              void do_advance(It& it, typename
       std::iterator_traits<It>::difference_type n,
                              std::input_iterator_tag)
              {
                  while (n > 0)
                  {
                      --n;
                      ++it;
                  }
              }

              template<class It>
              void do_advance(It& it, typename
       std::iterator_traits<It>::difference_type n,
                              std::bidirectional_iterator_tag)
              {
                  while (n > 0)
                  {
                      --n;
                      ++it;
                  }
                  while (n < 0)
                  {
                      ++n;
                      --it;
                  }
              }

              template<class It>
              void do_advance(It& it, typename
       std::iterator_traits<It>::difference_type n,
                              std::random_access_iterator_tag)
              {
                  it += n;
              }
          } // namespace detail

          template<class It, class Distance>
          void advance(It& it, Distance n)
          {
              detail::do_advance(it, typename
       std::iterator_traits<It>::difference_type(n),
                                 typename
       std::iterator_traits<It>::iterator_category());
          }

🌟 constexpr version 🌟

          template<class It, class Distance>
          constexpr void advance(It& it, Distance n)
          {
              using category = typename
       std::iterator_traits<It>::iterator_category;
              static_assert(std::is_base_of_v<std::input_iterator_tag,
       category>);

              auto dist = typename
       std::iterator_traits<It>::difference_type(n);
              if constexpr (std::is_base_of_v<std::random_access_iterator_tag,
       category>)
                  it += dist;
              else
              {
                  while (dist > 0)
                  {
                      --dist;
                      ++it;
                  }
                  if constexpr
       (std::is_base_of_v<std::bidirectional_iterator_tag, category>)
                      while (dist < 0)
                      {
                          ++dist;
                          --it;
                      }
              }
          }

πŸ“ Example πŸ“

// Run this code

        #include <iostream>
        #include <iterator>
        #include <vector>

        int main()
        {
            std::vector<int> v{3, 1, 4};

            auto vi = v.begin();
            std::advance(vi, 2);
            std::cout << *vi << ' ';

            vi = v.end();
            std::advance(vi, -2);
            std::cout << *vi << '\n';
        }

πŸ“ Output πŸ“

4 1

🌈 See also 🌈

  • next β€” increment an iterator (C++11) (function template)
  • prev β€” decrement an iterator (C++11) (function template)
  • distance β€” returns the distance between two iterators (function template)
  • ranges::advance β€” advances an iterator by given distance or to a given bound (C++20) (niebloid)

That’s the whole vibe check, bestie: from http://cppreference.com, dated 2024.06.10, and yes the page is std::advance(3). πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from