std::ranges::binary_search(3)
std::ranges::binary_search π
okay so bestie, this is the std::ranges::binary_search page from the C++ Standard Library β manual section 3, folded in right here because we're cute like that. It's literally the βdoes this partitioned/sorted-ish range contain my value?β girlie, and she ate. no cap. π¦
NAME β¨
std::ranges::binary_search β std::ranges::binary_search
(yes, the name is the name. iconic.)
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
<const T*, std::projected<I, Proj>> Comp =
ranges::less >
(since C++20)
(until C++26)
constexpr bool binary_search( I first, S last, 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 =
ranges::less >
(since C++26)
constexpr bool binary_search( 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*,
std::projected<ranges::iterator_t<R>,
Proj>> Comp =
ranges::less >
(since C++20)
(until C++26)
constexpr bool binary_search( 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*,
std::projected<ranges::iterator_t<R>,
Proj>> Comp =
ranges::less >
(since C++26)
constexpr bool binary_search( R&& r, const T& value,
Comp comp = {}, Proj proj = {}
);
- Checks if a projected element equivalent to
valueappears within the range[first, last). - Same as (1), but uses
ras the source range, as if usingranges::begin(r)asfirstandranges::end(r)aslast.
For ranges::binary_search to succeed, the range [first, last) must be at least partially ordered with respect to value, i.e. it must satisfy all of the following requirements:
- partitioned with respect to
std::invoke(comp, std::invoke(proj, element), value)(that is, all projected elements for which the expression istrueprecedes all elements for which the expression isfalse). - partitioned with respect to
!std::invoke(comp, value, std::invoke(proj, element)). - for all elements, if
std::invoke(comp, std::invoke(proj, element), value)istruethen!std::invoke(comp, value, std::invoke(proj, element))is alsotrue.
A fully-sorted range meets these criteria.
bestie, this is the vibe check: the range has to be at least partially ordered with respect to value; a fully-sorted range meets these criteria. π«Ά
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.
Parameters πΈ
first, lastβ the range of elements to examine.rβ the range of elements to examine.valueβ value to compare the elements to.compβ comparison function to apply to the projected elements.projβ projection to apply to the elements.
Return value π
true if an element equal to value is found, false otherwise.
Complexity π₯
The number of comparisons and projections performed is logarithmic in the distance between first and last (at most logβ(last - first) + O(1) comparisons and projections). However, for an iterator-sentinel pair that does not model std::random_access_iterator, the number of iterator increments is linear.
Notes π§
std::ranges::binary_search doesn't return an iterator to the found element when an element whose projection equals value is found. If an iterator is desired, std::ranges::lower_bound should be used instead.
Feature-test macro tea β:
__cpp_lib_algorithm_default_value_typeβ value202403β(C++26)β feature: βList-initialization for algorithmsβ β applies to overloads(1,2).
Possible implementation π
struct binary_search_fn {
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 =
ranges::less>
constexpr bool operator()(I first, S last, const T& value,
Comp comp = {}, Proj proj = {}) const
{
auto x = ranges::lower_bound(first, last, value, comp, proj);
return (!(x == last) && !(std::invoke(comp, value,
std::invoke(proj, *x))));
}
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 bool operator()(R&& r, const T& value, Comp comp = {},
Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), value,
std::move(comp), std::move(proj));
} };
inline constexpr binary_search_fn binary_search;
Example π
// Run this code
#include <algorithm>
#include <cassert>
#include <complex>
#include <iostream>
#include <ranges>
#include <vector>
int main()
{
constexpr static auto haystack = {1, 3, 4, 5, 9};
static_assert(std::ranges::is_sorted(haystack));
for (const int needle : std::views::iota(1)
| std::views::take(3))
{
std::cout << "Searching for " << needle << ": ";
std::ranges::binary_search(haystack, needle)
? std::cout << "found " << needle << '\n'
: std::cout << "no dice!\n";
}
using CD = std::complex<double>;
std::vector<CD> nums{{1, 1}, {2, 3}, {4, 2}, {4, 3}};
auto cmpz = [](CD x, CD y){ return abs(x) < abs(y); };
#ifdef __cpp_lib_algorithm_default_value_type
assert(std::ranges::binary_search(nums, {4, 2}, cmpz));
#else
assert(std::ranges::binary_search(nums, CD{4, 2}, cmpz));
#endif
}
Output:
Searching for 1: found 1
Searching for 2: no dice!
Searching for 3: found 3
See also π
ranges::equal_range(C++20)(niebloid)β returns range of elements matching a specific key.ranges::lower_bound(C++20)(niebloid)β returns an iterator to the first element not less than the given value.ranges::upper_bound(C++20)(niebloid)β returns an iterator to the first element greater than a certain value.ranges::contains(C++23)andranges::contains_subrange(C++23)(niebloid)β checks if the range contains the given element or subrange.binary_search(function template)β determines if an element exists in a partially-ordered range.
mwah π source/version/date: http://cppreference.com, 2024.06.10, and the page is std::ranges::binary_search(3). bye bestie, go find your value π«Άβ¨
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms