Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

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

NAME
       std::ranges::partition -	std::ranges::partition

Synopsis
	  Defined in header <algorithm>
	  Call signature
	  template< std::permutable I, std::sentinel_for<I> S, class Proj =
	  std::identity,

	  std::indirect_unary_predicate<std::projected<I,    Proj>>   Pred   >
       (1) (since C++20)
	  constexpr ranges::subrange<I>

	  partition( I first, S	last, Pred pred, Proj proj = {}	);
	  template< ranges::forward_range R, class Proj	= std::identity,

	  std::indirect_unary_predicate<
	  std::projected<ranges::iterator_t<R>,	     Proj>>	  Pred	     >
       (2) (since C++20)
	  requires std::permutable<ranges::iterator_t<R>>
	  constexpr ranges::borrowed_subrange_t<R>

	  partition( R&& r, Pred pred, Proj proj = {} );

	  1)  Reorders	the  elements in the range [first, last) in such a way
       that the
	  projection proj of all elements for which the	predicate pred returns
       true precede
	  the projection proj of elements for  which  predicate	 pred  returns
       false. Relative
	  order	of elements is not preserved.
	  2)  Same  as	(1),  but  uses	 r  as	the  source range, as if using
       ranges::begin(r)	as
	  first	and ranges::end(r) as last.

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

	    * Explicit template	argument lists may not be specified when call-
       ing any of them.
	    * None of them is visible to argument-dependent lookup.
	    *  When  one of them is found by normal unqualified	lookup for the
       name to the left
	      of the function-call operator,  it  inhibits  argument-dependent
       lookup.

	  In  practice,	 they  may be implemented as function objects, or with
       special compiler
	  extensions.

Parameters
	  first, last -	the range of elements to reorder
	  r	      -	the range of elements to reorder
	  pred	      -	predicate to apply to the projected elements
	  proj	      -	projection to apply to the elements.

Return value
	  A subrange starting with an iterator to the  first  element  of  the
       second group and
	  finishing   with   an	  iterator   equal   to	  last.	  (2)  returns
       std::ranges::dangling if	r is
	  an rvalue of non-borrowed_range type.

Complexity
	  Given	N = ranges::distance(first,last), exactly  N  applications  of
       the predicate and
	  projection.  At most N/2 swaps if I models ranges::bidirectional_it-
       erator, and at
	  most N swaps otherwise.

Possible implementation
	  struct partition_fn {
	    template<std::permutable I,	std::sentinel_for<I> S,	class  Proj  =
       std::identity,
		     std::indirect_unary_predicate<std::projected<I,	Proj>>
       Pred>
	    constexpr ranges::subrange<I>
	    operator()(I first,	S last,	Pred pred, Proj	proj = {}) const
	    {
		first  =  ranges::find_if_not(first,   last,   std::ref(pred),
       std::ref(proj));
		if (first == last) {
		    return {first, first};
		}

		auto begin = first;
		for (auto i = ranges::next(first); i !=	last; ++i) {
		    if (std::invoke(pred, std::invoke(proj, *i))) {
			ranges::iter_swap(i, first);
			++first;
		    }
		}
		return {std::move(first), std::move(last)};
	    }

	    template<ranges::forward_range R, class Proj = std::identity,
		     std::indirect_unary_predicate<
			 std::projected<ranges::iterator_t<R>, Proj>> Pred>
	    requires std::permutable<ranges::iterator_t<R>>
	    constexpr ranges::borrowed_subrange_t<R>
	    operator()(R&& r, Pred pred, Proj proj = {}) const
	    {
	      return (*this)(ranges::begin(r), ranges::end(r),
			     std::ref(pred), std::ref(proj));
	    }
	  };

	  inline constexpr partition_fn	partition;

Example
       // Run this code

	#include <algorithm>
	#include <forward_list>
	#include <functional>
	#include <iostream>
	#include <iterator>
	#include <ranges>
	#include <vector>

	namespace ranges = std::ranges;

	template <class	I, std::sentinel_for<I>	S, class Cmp = ranges::less>
	requires std::sortable<I, Cmp>
	void quicksort(I first,	S last,	Cmp cmp	= Cmp{})
	{
	    using reference = std::iter_reference_t<I>;

	    if (first == last)
		return;

	    auto size =	ranges::distance(first,	last);
	    auto pivot = ranges::next(first, size - 1);
	    ranges::iter_swap(pivot, ranges::next(first, size /	2));

	    ranges::subrange tail = ranges::partition(first, pivot, [=](refer-
       ence em)	{
		// em <	pivot
		return std::invoke(cmp,	em, *pivot);
	    });

	    ranges::iter_swap(pivot, tail.begin());
	    quicksort(first, tail.begin(), std::ref(cmp));
	    quicksort(ranges::next(tail.begin()), last,	std::ref(cmp));
	}

	int main()
	{
	    std::ostream_iterator<int> cout {std::cout,	" "};

	    std::vector<int> v {0,1,2,3,4,5,6,7,8,9};
	    std::cout << "Original vector:  \t";
	    ranges::copy(v, cout);

	    auto tail =	ranges::partition(v, [](int i){return i	% 2 == 0;});

	    std::cout << "\nPartitioned	vector:	\t";
	    ranges::copy(ranges::begin(v), ranges::begin(tail),	cout);
	    std::cout << " ";
	    ranges::copy(tail, cout);

	    std::forward_list<int>  fl	{1, 30,	-4, 3, 5, -4, 1, 6, -8,	2, -5,
       64, 1, 92};
	    std::cout << "\nUnsorted list: \t\t";
	    ranges::copy(fl, cout);

	    quicksort(ranges::begin(fl), ranges::end(fl), ranges::greater{});
	    std::cout << "\nQuick-sorted list: \t";
	    ranges::copy(fl, cout);

	    std::cout << '\n';
	}

Possible output:
	Original vector:	0 1 2 3	4 5 6 7	8 9
	Partitioned vector:	0 8 2 6	4  5 3 7 1 9
	Unsorted list:		1 30 -4	3 5 -4 1 6 -8 2	-5 64 1	92
	Quick-sorted list:	92 64 30 6 5 3 2 1 1 1 -4 -4 -5	-8

See also
	  ranges::partition_copy   copies a range dividing the	elements  into
       two groups
	  (C++20)		   (niebloid)
	  ranges::is_partitioned    determines	if the range is	partitioned by
       the given
	  (C++20)		   predicate
				   (niebloid)
	  ranges::stable_partition divides elements into two groups while pre-
       serving their
	  (C++20)		   relative order
				   (niebloid)
	  partition		   divides a range of elements into two	groups
				   (function template)

http://cppreference.com		  2022.07.31	     std::ranges::partition(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::ranges::partition&sektion=3&manpath=FreeBSD+Ports+15.0>

home | help