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

FreeBSD Manual Pages

  
 
  

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

NAME
       std::ranges::equal_range	- std::ranges::equal_range

Synopsis
	  Defined in header <algorithm>
	  Call signature
	  template< std::forward_iterator I, std::sentinel_for<I> S,

		    class T, class Proj	= std::identity,
		    std::indirect_strict_weak_order
       (since
			<const	  T*,	 std::projected<I,   Proj>>   Comp   =
       C++20)
	  ranges::less							     >
       (until
	  constexpr   ranges::subrange<I>   equal_range(   I  first,  S	 last,
       C++26)
	  const	T& value,

						     Comp comp = {},
	  Proj proj = {} );
	  template< std::forward_iterator I, std::sentinel_for<I> S,

		    class Proj = std::identity,
		    class T = std::projected_value_t<I,	Proj>,
		    std::indirect_strict_weak_order
			<const	 T*,   std::projected<I,   Proj>>    Comp    =
       (since
	  ranges::less							     >
       C++26)
	  constexpr ranges::subrange<I>	equal_range( I first, S	last,
	  const	T& value,

						     Comp comp = {},
	  Proj proj = {} );
	  template< ranges::forward_range R,
								       (1)
		    class T, class Proj	= std::identity,
		    std::indirect_strict_weak_order
			<const						   T*,
       (since
	  std::projected<ranges::iterator_t<R>,
       C++20)
						  Proj>>	 Comp	     =
       (until
	  ranges::less							     >
       C++26)
	  constexpr ranges::borrowed_subrange_t<R>

	      equal_range( R&& r, const	T& value, Comp comp = {}, Proj
	  proj = {} );
	  template< ranges::forward_range R,				   (2)

		    class Proj = std::identity,
		    class T =
	  std::projected_value_t<ranges::iterator_t<R>,	Proj>,
		    std::indirect_strict_weak_order
			<const						   T*,
       (since
	  std::projected<ranges::iterator_t<R>,
       C++26)
						  Proj>> Comp =
	  ranges::less >
	  constexpr ranges::borrowed_subrange_t<R>

	      equal_range( R&& r, const	T& value, Comp comp = {}, Proj
	  proj = {} );

	  1) Returns a view containing all elements equivalent to value	in the
       range
	  [first, last).

	  The range [first, last) must be at least partially ordered with  re-
       spect to	value,
	  i.e. it must satisfy all of the following requirements:

	    *  partitioned  with  respect  to element <	value or comp(element,
       value) (that is,
	      all elements for which the expression is true precedes all  ele-
       ments for which
	      the expression is	false).
	    *  partitioned  with respect to !(value < element) or !comp(value,
       element).
	    * for all elements,	if element < value or comp(element, value)  is
       true then
	      !(value <	element) or !comp(value, element) is also true.

	  A fully-sorted range meets these criteria.

	  The returned view is constructed from	two iterators, one pointing to
       the first
	  element  that	 is  not  less	than value and another pointing	to the
       first element
	  greater than value. The first	iterator may be	alternatively obtained
       with
	  std::ranges::lower_bound(),  the  second  -  with   std::ranges::up-
       per_bound().

	  2)  Same  as	(1),  but  uses	r as the source	range, as if using the
       range
	  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	cannot be specified when call-
       ing 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 in-
       hibited.

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

Parameters
	  first, last -	the range of elements to examine
	  r	      -	the range of the elements to examine
	  value	      -	value to compare the elements to
	  comp	       -  if  the first	argument is less than (i.e. is ordered
       before) the second
	  proj	      -	projection to apply to the elements

Return value
	  std::ranges::subrange	containing a pair of  iterators	 defining  the
       wanted range, the
	  first	 pointing to the first element that is not less	than value and
       the second
	  pointing to the first	element	greater	than value.

	  If there are no elements not less than value,	the last iterator (it-
       erator that is
	  equal	to last	or ranges::end(r)) is returned as the  first  element.
       Similarly if
	  there	 are  no elements greater than value, the last iterator	is re-
       turned as the
	  second element.

Complexity
	  The number of	comparisons performed is logarithmic in	 the  distance
       between first and
	  last (at most	2 * log
	  2(last  -  first) + O(1) comparisons). However, for an iterator that
       does not	model
	  random_access_iterator, the number of	iterator increments is linear.

Possible implementation
	struct equal_range_fn
	{
	    template<std::forward_iterator I, std::sentinel_for<I> S,
		     class  Proj  =  std::identity,  class   T	 =   std::pro-
       jected_value_t<I, Proj>,
		     std::indirect_strict_weak_order
			 <const	   T*,	 std::projected<I,   Proj>>   Comp   =
       ranges::less>
	    constexpr ranges::subrange<I>
		operator()(I first, S last, const T& value, Comp  comp	=  {},
       Proj proj = {}) const
	    {
		return ranges::subrange
		(
		    ranges::lower_bound(first,	last,  value,  std::ref(comp),
       std::ref(proj)),
		    ranges::upper_bound(first,	last,  value,  std::ref(comp),
       std::ref(proj))
		);
	    }

	    template<ranges::forward_range R, class Proj = std::identity,
		     class  T  = std::projected_value_t<ranges::iterator_t<R>,
       Proj>,
		     std::indirect_strict_weak_order
			 <const	T*, std::projected<ranges::iterator_t<R>,
						   Proj>> Comp = ranges::less>
	    constexpr ranges::borrowed_subrange_t<R>
		operator()(R&& r, const	T& value, Comp comp = {}, Proj proj  =
       {}) const
	    {
		return (*this)(ranges::begin(r), ranges::end(r), value,
			       std::ref(comp), std::ref(proj));
	    }
	};

	inline constexpr equal_range_fn	equal_range;

Notes
		    Feature-test       macro		     Value	   Std
       Feature
	  __cpp_lib_algorithm_default_value_type 202403	(C++26)	 List-initial-
       ization for
								algorithms
       (1,2)

Example
       // Run this code

	#include <algorithm>
	#include <compare>
	#include <complex>
	#include <iostream>
	#include <vector>

	struct S
	{
	    int	number {};
	    char name {};
	    // note: name is ignored by	these comparison operators
	    friend bool	operator== (const S s1,	const S	s2) { return s1.number
       == s2.number; }
	    friend auto	operator<=>(const S s1,	const S	s2) { return s1.number
       <=> s2.number; }
	    friend std::ostream& operator<<(std::ostream& os, S	o)
	    {
		return os << '{' << o.number <<	", '" << o.name	<< "'}";
	    }
	};

	void println(auto rem, const auto& v)
	{
	    for	(std::cout << rem; const auto& e : v)
		std::cout << e << ' ';
	    std::cout << '\n';
	}

	int main()
	{
	    // note: not ordered, only partitioned w.r.t. S defined below
	    std::vector<S> vec
	    {
		{1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {4,	'D'}, {4,'G'}, {3,'F'}
	    };

	    const S value{2, '?'};

	    namespace ranges = std::ranges;

	    auto a = ranges::equal_range(vec, value);
	    println("1.	", a);

	    auto b = ranges::equal_range(vec.begin(), vec.end(), value);
	    println("2.	", b);

	    auto c = ranges::equal_range(vec, 'D', ranges::less	{}, &S::name);
	    println("3.	", c);

	    auto   d   =   ranges::equal_range(vec.begin(),   vec.end(),  'D',
       ranges::less {},	&S::name);
	    println("4.	", d);

	    using CD = std::complex<double>;
	    std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}};
	    auto cmpz =	[](CD x, CD y) { return	x.real() < y.real(); };
	    #ifdef __cpp_lib_algorithm_default_value_type
		auto p3	= ranges::equal_range(nums, {2,	0}, cmpz);
	    #else
		auto p3	= ranges::equal_range(nums, CD{2, 0}, cmpz);
	    #endif
	    println("5.	", p3);
	}

Output:
	1. {2, 'B'} {2,	'C'} {2, 'D'}
	2. {2, 'B'} {2,	'C'} {2, 'D'}
	3. {2, 'D'} {4,	'D'}
	4. {2, 'D'} {4,	'D'}
	5. (2,2) (2,1)

See also
	  ranges::lower_bound	returns	an iterator to the first  element  not
       less than the
	  (C++20)		given value
				(niebloid)
	  ranges::upper_bound	 returns  an  iterator	to  the	 first element
       greater than a
	  (C++20)		certain	value
				(niebloid)
	  ranges::binary_search	determines if an  element  exists  in  a  par-
       tially-ordered range
	  (C++20)		(niebloid)
	  ranges::partition	divides	a range	of elements into two groups
	  (C++20)		(niebloid)
	  ranges::equal		 determines  if	 two  sets of elements are the
       same
	  (C++20)		(niebloid)
	  equal_range		returns	range of elements matching a  specific
       key
				(function template)

http://cppreference.com		  2024.06.10	   std::ranges::equal_range(3)

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

home | help