std::ranges...:find_if_not(3)
π¦ std::ranges...:find_if_not(3) β from the C++ Standard Libary manual π
πΈ NAME πΈ
std::ranges::find,std::ranges::find_if,std::ranges::find_if_not β std::ranges::find,std::ranges::find_if,std::ranges::find_if_not
Bestie, itβs the whole find / find_if / find_if_not trio in ranges form. Iconic behavior honestly.
β¨ Synopsis β¨
First things first: itβs all Defined in header <algorithm>, and hereβs the call signature situation exactly as the manual serves it:
Defined in header <algorithm>
Call signature
template< std::input_iterator I, std::sentinel_for<I> S,
class T, class Proj = std::identity >
(since
requires std::indirect_binary_predicate
C++20)
<ranges::equal_to, std::projected<I, Proj>,
(until
const T*>
C++26)
constexpr I find( I first, S last, const T& value, Proj proj
= {} );
template< std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
class T = std::projected_value_t<I, Proj> >
requires std::indirect_binary_predicate
(since
<ranges::equal_to, std::projected<I, Proj>,
C++26)
const T*>
constexpr I find( I first, S last, const T& value, Proj proj
= {} );
template< ranges::input_range R, class T, class Proj =
std::identity >
requires std::indirect_binary_predicate
(since
<ranges::equal_to,
C++20)
std::projected<ranges::iterator_t<R>, Proj>,
(until
const T*>
C++26)
constexpr ranges::borrowed_iterator_t<R>
find( R&& r, const T& value, Proj proj = {} );
template< ranges::input_range R, class Proj = std::identity,
class T =
std::projected_value_t<ranges::iterator_t<R>, Proj> >
requires std::indirect_binary_predicate
(since
<ranges::equal_to,
C++26)
std::projected<ranges::iterator_t<R>, Proj>, (1)
const T*>
constexpr ranges::borrowed_iterator_t<R>
find( R&& r, const T& value, Proj proj = {} );
template< std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I,
(3) (since
Proj>> Pred >
C++20)
(2)
constexpr I find_if( I first, S last, Pred pred, Proj proj =
{} );
template< ranges::input_range R, class Proj = std::identity,
std::indirect_unary_predicate
<std::projected<ranges::iterator_t<R>, Proj>>
(4) (since
Pred >
C++20)
constexpr ranges::borrowed_iterator_t<R>
find_if( R&& r, Pred pred, Proj proj = {} );
template< std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
std::indirect_unary_predicate<std::projected<I,
(5) (since
Proj>> Pred >
C++20)
constexpr I find_if_not( I first, S last, Pred pred, Proj
proj = {} );
template< ranges::input_range R, class Proj = std::identity,
std::indirect_unary_predicate
<std::projected<ranges::iterator_t<R>, Proj>>
(6) (since
Pred >
C++20)
constexpr ranges::borrowed_iterator_t<R>
find_if_not( R&& r, Pred pred, Proj proj = {} );
Okay so the whole point: these return the first element in the range [first, last) that satisfies the specific criteria:
1)findsearches for an element equal tovalue.3)find_ifsearches for an element for which predicatepredreturnstrue.5)find_if_notsearches for an element for which predicatepredreturnsfalse.2,4,6)Same as(1,3,5), but usesras the source range, as if usingranges::begin(r)asfirstandranges::end(r)aslast.
Now the vibe check: 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. No cap.
π Parameters π
first,lastβ the range of elements to examinerβ the range of the elements to examinevalueβ value to compare the elements topredβ predicate to apply to the projected elementsprojβ projection to apply to the elements
π¦ Return value π¦
Iterator to the first element satisfying the condition, or iterator equal to last if no such element is found. Periodt.
π₯ Complexity π₯
At most last - first applications of the predicate and projection. Thatβs the budget, bestie.
π Possible implementation π
β¨ find β¨
struct find_fn
{
template<std::input_iterator I, std::sentinel_for<I> S,
class Proj = std::identity,
class T = std::projected_value_t<I, Proj>>
requires std::indirect_binary_predicate
<ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr I operator()(I first, S last, const T& value, Proj proj =
{}) const
{
for (; first != last; ++first)
if (std::invoke(proj, *first) == value)
return first;
return first;
}
template<ranges::input_range R, class T, class Proj =
std::identity>
requires std::indirect_binary_predicate<ranges::equal_to,
std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::borrowed_iterator_t<R>
operator()(R&& r, const T& value, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), value,
std::ref(proj));
}
};
inline constexpr find_fn find;
β¨ find_if β¨
struct find_if_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class Proj
= std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>>
Pred>
constexpr I operator()(I first, S last, Pred pred, Proj proj = {})
const
{
for (; first != last; ++first)
if (std::invoke(pred, std::invoke(proj, *first)))
return first;
return first;
}
template<ranges::input_range R, class Proj = std::identity,
std::indirect_unary_predicate
<std::projected<ranges::iterator_t<R>, Proj>> Pred>
constexpr ranges::borrowed_iterator_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 find_if_fn find_if;
β¨ find_if_not β¨
struct find_if_not_fn
{
template<std::input_iterator I, std::sentinel_for<I> S, class Proj
= std::identity,
std::indirect_unary_predicate<std::projected<I, Proj>>
Pred>
constexpr I operator()(I first, S last, Pred pred, Proj proj = {})
const
{
for (; first != last; ++first)
if (!std::invoke(pred, std::invoke(proj, *first)))
return first;
return first;
}
template<ranges::input_range R, class Proj = std::identity,
std::indirect_unary_predicate
<std::projected<ranges::iterator_t<R>, Proj>> Pred>
constexpr ranges::borrowed_iterator_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 find_if_not_fn find_if_not;
β Notes β
Feature-test macro tea:
- Feature-test macro:
__cpp_lib_algorithm_default_value_typeβ Value:202403β Std:(C++26)β Feature: List-initialization for algorithms(1,2)
π» EXAMPLE π»
okay bestie, this demo is literally the whole vibe β itβs got projector_example(), main(), the std::complex moment, all of it. Run it and the output below is exactly what you get. π
β¨
// Run this code
#include <algorithm>
#include <cassert>
#include <complex>
#include <format>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
void projector_example()
{
struct folk_info
{
unsigned uid;
std::string name, position;
};
std::vector<folk_info> folks
{
{0, "Ana", "dev"},
{1, "Bob", "devops"},
{2, "Eve", "ops"}
};
const auto who{"Eve"};
if (auto it = std::ranges::find(folks, who, &folk_info::name); it != folks.end())
std::cout << std::format("Profile:\n"
" UID: {}\n"
" Name: {}\n"
" Position: {}\n\n",
it->uid, it->name, it->position);
}
int main()
{
namespace ranges = std::ranges;
projector_example();
const int n1 = 3;
const int n2 = 5;
const auto v = {4, 1, 3, 2};
if (ranges::find(v, n1) != v.end())
std::cout << "v contains: " << n1 << '\n';
else
std::cout << "v does not contain: " << n1 << '\n';
if (ranges::find(v.begin(), v.end(), n2) != v.end())
std::cout << "v contains: " << n2 << '\n';
else
std::cout << "v does not contain: " << n2 << '\n';
auto is_even = [](int x) { return x % 2 == 0; };
if (auto result = ranges::find_if(v.begin(), v.end(), is_even); result != v.end())
std::cout << "First even element in v: " << *result << '\n';
else
std::cout << "No even elements in v\n";
if (auto result = ranges::find_if_not(v, is_even); result != v.end())
std::cout << "First odd element in v: " << *result << '\n';
else
std::cout << "No odd elements in v\n";
auto divides_13 = [](int x) { return x % 13 == 0; };
if (auto result = ranges::find_if(v, divides_13); result != v.end())
std::cout << "First element divisible by 13 in v: " << *result << '\n';
else
std::cout << "No elements in v are divisible by 13\n";
if (auto result = ranges::find_if_not(v.begin(), v.end(), divides_13);
result != v.end())
std::cout << "First element indivisible by 13 in v: " << *result << '\n';
else
std::cout << "All elements in v are divisible by 13\n";
std::vector<std::complex<double>> nums{{4, 2}};
#ifdef __cpp_lib_algorithm_default_value_type
// T gets deduced in (2) making list-initialization possible
const auto it = ranges::find(nums, {4, 2});
#else
const auto it = ranges::find(nums, std::complex<double>{4, 2});
#endif
assert(it == nums.begin());
}
π€ Output π€
and the output is giving exactly this:
Profile:
UID: 2
Name: Eve
Position: ops
v contains: 3
v does not contain: 5
First even element in v: 4
First odd element in v: 1
No elements in v are divisible by 13
First element indivisible by 13 in v: 4
π SEE ALSO π
ranges::adjacent_findβ finds the first two adjacent items that are equal (or satisfy a given predicate);(C++20),(niebloid).ranges::find_endβ finds the last sequence of elements in a certain range;(C++20),(niebloid).ranges::find_first_ofβ searches for any one of a set of elements;(C++20),(niebloid).ranges::mismatchβ finds the first position where two ranges differ;(C++20),(niebloid).ranges::searchβ searches for a range of elements;(C++20),(niebloid).find,find_if,find_if_notβ finds the first element satisfying specific criteria;find_if_notis(function template),(C++11).
thatβs the page, bestie π«Ά source is cppreference.com, dated/versioned 2024.06.10, page std::ranges...:find_if_not(3). mwah ππ
π¦ 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