home | help
std::advance(3) 	       C++ Standard Libary		 std::advance(3)

NAME
     std::advance - std::advance

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.

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)

Complexity
	Linear.

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

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.

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>::differ-
     ence_type n,
			    std::input_iterator_tag)
	    {
		while (n > 0)
		{
		    --n;
		    ++it;
		}
	    }

	    template<class It>
	    void  do_advance(It&  it, typename std::iterator_traits<It>::differ-
     ence_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>::differ-
     ence_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>::differ-
     ence_type(n),
			       typename std::iterator_traits<It>::iterator_cate-
     gory());
	}
					 constexpr version
	template<class It, class Distance>
	constexpr void advance(It& it, Distance n)
	{
	    using category =  typename	std::iterator_traits<It>::iterator_cate-
     gory;
	    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)

http://cppreference.com 	   2024.06.10			 std::advance(3)

home | help