std::ranges::prev(3)

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

πŸ’– NAME πŸ’–

okay so bestie, this page's title is std::ranges::prev, and the manual name is C++ Standard Library β€” we're folding that in right here instead of copying a boring header line, periodt. The NAME vibe is literally std::ranges::prev - std::ranges::prev. iconic, we love a self-referential moment πŸ’…

✨ Synopsis ✨

          Defined in header <iterator>
          Call signature
          template< std::bidirectional_iterator I >                      (1)
       (since C++20)
          constexpr I prev( I i );
          template< std::bidirectional_iterator I >                      (2)
       (since C++20)
          constexpr I prev( I i, std::iter_difference_t<I> n );
          template< std::bidirectional_iterator I >                      (3)
       (since C++20)
          constexpr I prev( I i, std::iter_difference_t<I> n, I bound );

so what does it do? it's giving return the n^th predecessor of iterator i β€” like, walk that iterator backwards, bestie 🫢

The function-like entities described on this page are niebloids, that is:

  • Explicit template argument lists cannot be specified when calling any of them.
  • None of them are visible to argument-dependent lookup.
  • When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.

In practice, they may be implemented as function objects, or with special compiler extensions. no cap, that's the whole vibe check ✨

🫢 Parameters 🫢

  • i β€” an iterator.
  • n β€” number of elements i should be descended.
  • bound β€” iterator denoting the beginning of the range i points to.

πŸ’… Return value πŸ’…

  1. The predecessor of i.
  2. The n^th predecessor of iterator i.
  3. The n^th predecessor of iterator i, or the first iterator that compares equal to bound, whichever is first.

πŸŒ€ Complexity πŸŒ€

  • 1 β€” Constant.
  • 2,3 β€” Constant if I models std::random_access_iterator<I>; otherwise linear.

πŸ› οΈ Possible implementation πŸ› οΈ

struct prev_fn
{
    template<std::bidirectional_iterator I>
    constexpr I operator()(I i) const
    {
        --i;
        return i;
    }

    template<std::bidirectional_iterator I>
    constexpr I operator()(I i, std::iter_difference_t<I> n) const
    {
        ranges::advance(i, -n);
        return i;
    }

    template<std::bidirectional_iterator I>
    constexpr I operator()(I i, std::iter_difference_t<I> n, I bound) const
    {
        ranges::advance(i, -n, bound);
        return i;
    }
};

inline constexpr auto prev = prev_fn();

πŸ‘€ Notes πŸ‘€

Although the expression --r.end() often compiles for containers, it is not guaranteed to do so: r.end() is an rvalue expression, and there is no iterator requirement that specifies that decrement of an rvalue is guaranteed to work. In particular, when iterators are implemented as pointers or its operator-- is lvalue-ref-qualified, --r.end() does not compile, while ranges::prev(r.end()) does. πŸ’€

This is further exacerbated by ranges that do not model ranges::common_range. For example, for some underlying ranges, ranges::transform_view::end doesn't have the same return type as ranges::transform_view::begin, and so --r.end() won't compile. This isn't something ranges::prev can aid with, but there are workarounds. bestie, sometimes the range is just extra like that 😭

🌸 Example 🌸

// Run this code

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

int main()
{
    std::vector<int> v{3, 1, 4};
    auto pv = std::ranges::prev(v.end(), 2);
    std::cout << *pv << '\n';

    pv = std::ranges::prev(pv, 42, v.begin());
    std::cout << *pv << '\n';
}

Output:

1
3

πŸ‘‘ See also πŸ‘‘

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

okay that's the whole page bestie, mwah πŸ’‹ β€” source: http://cppreference.com, version/date: 2024.06.10, page: std::ranges::prev(3). byeee πŸ¦‹

πŸ“¦ where this page comes from