Skip to main content

std::ranges::find_if() algorithm

// (1)
constexpr I
find_if( I first, S last, Pred pred, Proj proj = {} );

// (2)
constexpr ranges::borrowed_iterator_t<R>
find_if( R&& r, Pred pred, Proj proj = {} );

The type of arguments are generic and have the following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • Proj - (none)
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>
  • (2) - R - std::ranges::input_range

The Proj template argument has a default type of std::identity for all overloads.

Returns an iterator to the first element in the range satisfiying specific criteria (or last iterator if there is no such iterator):

  • (1) Searches for an element for which predicate p returns true.

  • (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.

Parameters

first
last

The range of elements to examine.

r

The range of elements to examine.

pred

Predicate to apply to the projected elements.

proj

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.

Complexity

At most last - first applications of the predicate and projection.

Exceptions

(none)

Possible implementation

find_if(1)
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;

Examples

Main.cpp
#include <algorithm>
#include <iostream>
#include <iterator>

int main()
{
namespace ranges = std::ranges;

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";
}
Output
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
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::ranges::find_if() algorithm

// (1)
constexpr I
find_if( I first, S last, Pred pred, Proj proj = {} );

// (2)
constexpr ranges::borrowed_iterator_t<R>
find_if( R&& r, Pred pred, Proj proj = {} );

The type of arguments are generic and have the following constraints:

  • I - std::input_iterator
  • S - std::sentinel_for<I>
  • Proj - (none)
  • Pred:
    • (1) - std::indirect_unary_predicate<std::projected<I, Proj>>
    • (2) - std::indirect_unary_predicate<std::projected<ranges::iterator_t<R>, Proj>>
  • (2) - R - std::ranges::input_range

The Proj template argument has a default type of std::identity for all overloads.

Returns an iterator to the first element in the range satisfiying specific criteria (or last iterator if there is no such iterator):

  • (1) Searches for an element for which predicate p returns true.

  • (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.

Parameters

first
last

The range of elements to examine.

r

The range of elements to examine.

pred

Predicate to apply to the projected elements.

proj

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.

Complexity

At most last - first applications of the predicate and projection.

Exceptions

(none)

Possible implementation

find_if(1)
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;

Examples

Main.cpp
#include <algorithm>
#include <iostream>
#include <iterator>

int main()
{
namespace ranges = std::ranges;

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";
}
Output
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
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.