std::prev(3)

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

πŸ’– std::prev β€” C++ Standard Libary (std::prev(3)) πŸ’–

okay bestie, welcome to the std::prev(3) page β€” yes, the manual name says C++ Standard Libary, typo and all, and we’re keeping it πŸ’€. This is the whole vibe: std::prev is that iconic little iterator-time-traveler, and she’s here to help you go backward (or forward if n is negative, plot twist ✨).


🌸 NAME 🌸

std::prev β€” std::prev (yes bestie, that’s the whole name, periodt πŸ’…).


✨ Synopsis ✨

Defined in header <iterator>.

(since C++11) / (until C++17) β€” the first shape of this icon:

template< class BidirIt >
BidirIt prev( BidirIt it, typename
std::iterator_traits<BidirIt>::difference_type n = 1 );

(since C++17) β€” now with constexpr energy 🌟:

template< class BidirIt >
constexpr
BidirIt prev( BidirIt it, typename
std::iterator_traits<BidirIt>::difference_type n = 1 );

Return the n^th predecessor (or -n^th successor if n is negative) of iterator it.


🫢 Parameters 🫢

  • it β€” an iterator. literally the iterator we’re moving from πŸ¦‹
  • n β€” number of elements it should be descended. lowkey the step count, bestie ✨

πŸŽ€ Type requirements πŸŽ€

  • BidirIt must meet the requirements of LegacyBidirectionalIterator. vibe check: it’s gotta be bidirectional, no cap πŸ’…

🌈 Return value 🌈

An iterator of type BidirIt that holds the n^th predecessor (or -n^th successor if n is negative) of iterator it. it’s giving β€œsame iterator type, new position” πŸ”₯


⭐ Complexity ⭐

Linear. highkey expected for a nice little walk through the container πŸšΆβ€β™€οΈ

However, if BidirIt additionally meets the requirements of LegacyRandomAccessIterator, complexity is constant. so if it’s a random-access bestie, she teleports ⚑


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

okay this is the little implementation moment, and I’m obsessed:

template<class BidirIt>
constexpr // since C++17
BidirIt prev(BidirIt it, typename
std::iterator_traits<BidirIt>::difference_type n = 1)
{
    std::advance(it, -n);
    return it;
}

std::advance(it, -n); and then return it; β€” simple, clean, iconic πŸŽ€


πŸ’€ Notes πŸ’€

⚠️ bestie, listen: although the expression --c.end() often compiles, it is not guaranteed to do so. c.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, --c.end() does not compile, while std::prev(c.end()) does. fr fr, this is the β€œuse std::prev and breathe” moment πŸ˜­πŸ’…

πŸ“ Example πŸ“

// Run this code

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

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

    auto it = v.end();
    auto pv = std::prev(it, 2);
    std::cout << *pv << '\n';

    it = v.begin();
    pv = std::prev(it, -2);
    std::cout << *pv << '\n';
}

Output πŸ“

1
4

ate. no crumbs. πŸ’…βœ¨


πŸ‘‘ See also πŸ‘‘

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

mwah πŸ’‹ β€” source: http://cppreference.com, version/date: 2024.06.10, page: std::prev(3). stay iterating, bestie πŸ«ΆπŸ’–

πŸ“¦ where this page comes from