C++ <algorithm> std::find_if_not

The std::find_if_not function in C++ is part of the <algorithm> header and is used to search for the first element in a range that does not satisfy a specified condition, defined by a unary predicate. If such an element is found, it returns an iterator to it; otherwise, it returns the end iterator.


Syntax of std::find_if_not

</>
Copy
template <class InputIterator, class UnaryPredicate>
InputIterator find_if_not(InputIterator first, InputIterator last, UnaryPredicate pred);

Parameters of std::find_if_not

ParameterDescription
firstAn input iterator to the initial position in a sequence.
lastAn input iterator to the final position in a sequence (one past the last element).
predA unary predicate that accepts an element in the range as an argument and returns a value convertible to bool. The value returned indicates whether the element satisfies the condition. The function shall not modify its argument. This can either be a function pointer or a function object.

Return Value of std::find_if_not

An iterator to the first element in the range for which pred returns false. If pred returns true for all elements, the function returns last.


Exceptions for std::find_if_not

Throws if either pred or an operation on an iterator throws. Note that invalid parameters cause undefined behavior.


Examples for std::find_if_not

Example 1: Using std::find_if_not to Find the First Even Number

In this example, we use std::find_if_not to search for the first even number in a vector.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm> // For std::find_if_not

bool is_odd(int n) {
    return n % 2 != 0;
}

int main() {
    std::vector<int> numbers = {1, 3, 5, 6, 7};

    auto it = std::find_if_not(numbers.begin(), numbers.end(), is_odd);

    if (it != numbers.end())
        std::cout << "The first even number is " << *it << '\n';
    else
        std::cout << "No even numbers found\n";

    return 0;
}

Output

The first even number is 6

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <vector> for the std::vector container, and <algorithm> for the std::find_if_not function.
  2. We define a function is_odd that takes an integer and returns true if the integer is odd, and false otherwise.
  3. We create a vector numbers containing the integers 1, 3, 5, 6, and 7.
  4. We use std::find_if_not to search for the first even number in the vector by passing the is_odd function as the predicate.
  5. If an even number is found, it points to the element, and we print its value. Otherwise, we print that no even numbers were found.

Example 2: Using std::find_if_not with a Lambda Function

This example demonstrates how to use std::find_if_not with a lambda function to find the first number not greater than 10 in a vector.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm> // For std::find_if_not

int main() {
    std::vector<int> numbers = {12, 15, 8, 20, 25};

    auto it = std::find_if_not(numbers.begin(), numbers.end(), [](int n) {
        return n > 10;
    });

    if (it != numbers.end())
        std::cout << "The first number not greater than 10 is " << *it << '\n';
    else
        std::cout << "All numbers are greater than 10\n";

    return 0;
}

Output

The first number not greater than 10 is 8

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <vector> for the std::vector container, and <algorithm> for the std::find_if_not function.
  2. We create a vector numbers containing the integers 12, 15, 8, 20, and 25.
  3. We use std::find_if_not with a lambda function that takes an integer and returns true if the integer is greater than 10.
  4. If a number not greater than 10 is found, it points to the element, and we print its value. Otherwise, we print that all numbers are greater than 10.

Example 3: Using std::find_if_not with a Custom Predicate

In this example, we use std::find_if_not to find the first string in a vector that does not start with the letter ‘A’.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

bool start_with_A(const std::string& s) {
    return s.empty() || s[0] == 'A';
}

int main() {
    std::vector<std::string> names = {"Alice", "Bob", "Anna", "Charlie"};

    auto it = std::find_if_not(names.begin(), names.end(), start_with_A);

    if (it != names.end()) {
        std::cout << "The first name not starting with 'A' is " << *it << '\n';
    } else {
        std::cout << "All names start with 'A'.\n";
    }

    return 0;
}

Output

The first name not starting with 'A' is Bob

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <vector> for the std::vector container, <string> for handling strings, and <algorithm> for the std::find_if_not function.
  2. We define a predicate function start_with_A that checks if a string starts with the letter ‘A’.
  3. We create a vector names containing the strings “Alice”, “Bob”, “Anna”, and “Charlie”.
  4. We use std::find_if_not to find the first name in the vector that does not start with the letter ‘A’.
  5. If a match is found, it points to the element, and we print its value. Otherwise, we print that all names start with ‘A’.

Examples for Exceptions Thrown by std::find_if_not

The std::find_if_not function can throw exceptions in the following cases:

  • If the predicate function (pred) throws an exception.
  • If an operation on the iterators, such as dereferencing or incrementing, throws an exception.

Example 1: Predicate Throws an Exception

This example demonstrates a case where the predicate function throws an exception during execution.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>

bool faulty_predicate(int n) {
    if (n < 0) {
        throw std::runtime_error("Negative number encountered.");
    }
    return n % 2 != 0;
}

int main() {
    std::vector<int> numbers = {1, 3, -5, 7, 9};

    try {
        auto it = std::find_if_not(numbers.begin(), numbers.end(), faulty_predicate);
        if (it != numbers.end()) {
            std::cout << "Element found: " << *it << std::endl;
        } else {
            std::cout << "No element satisfies the condition." << std::endl;
        }
    } catch (const std::runtime_error& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Output

Exception caught: Negative number encountered.

Explanation

  1. The program defines a predicate function faulty_predicate that throws a std::runtime_error if a negative number is encountered.
  2. A vector numbers is initialized, including a negative number (-5).
  3. The std::find_if_not function applies the predicate to each element of the vector. When it encounters the negative number, the predicate throws an exception.
  4. The exception is caught in the try-catch block, and an error message is displayed.

Example 2: Iterator Throws an Exception

This example demonstrates a case where a custom iterator throws an exception during iteration.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>

class FaultyIterator {
public:
    using iterator_category = std::input_iterator_tag;
    using value_type = int;
    using difference_type = std::ptrdiff_t;
    using pointer = const int*;
    using reference = const int&;

    FaultyIterator(const int* ptr, bool fail_after = false)
        : ptr(ptr), fail_after(fail_after), count(0) {}

    reference operator*() const {
        if (fail_after && count >= 2) {
            throw std::runtime_error("Iterator error during dereference.");
        }
        return *ptr;
    }

    FaultyIterator& operator++() {
        ++ptr;
        ++count;
        return *this;
    }

    bool operator!=(const FaultyIterator& other) const {
        return ptr != other.ptr;
    }

private:
    const int* ptr;
    bool fail_after;
    int count;
};

bool is_positive(int n) {
    return n > 0;
}

int main() {
    int arr[] = {1, 2, 3};

    try {
        auto it = std::find_if_not(
            FaultyIterator(arr, true),
            FaultyIterator(arr + 3),
            is_positive
        );

        if (it != FaultyIterator(arr + 3)) {
            std::cout << "Element found: " << *it << std::endl;
        } else {
            std::cout << "No element satisfies the condition." << std::endl;
        }
    } catch (const std::runtime_error& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Output

Exception caught: Iterator error during dereference.

Explanation

  1. The program defines a custom iterator FaultyIterator that throws a std::runtime_error exception after accessing two elements.
  2. An array arr is initialized with three elements.
  3. The std::find_if_not function searches for the first element that does not satisfy the predicate is_positive.
  4. The iterator throws an exception during the third access, which is caught in the try-catch block.
  5. An error message is printed to indicate the exception.