C++23stlexpert
std::ranges::find_last, find_last_if, find_last_if_not (C++23 Addition)
C++23 · Completing Modern · Compiler flag: -std=c++23
Explanation
Algorithms to find the last occurrence of a value or matching a predicate.
Real-World Scenario
Find the last error entry in a log file.
Quick Snippet
snippet.cpp
#include <ranges> auto it = std::ranges::find_last(vec, 42);Full Example
ranges_find_last.cpp
// CodeNebula - C++23 Example: ranges::find_last, find_last_if, find_last_if_not
// Compile: g++ -std=c++23 -Wall -Wextra -o example ranges_find_last.cpp
// Note: Requires GCC 13+ / Clang 17+
// C++23 adds find_last family algorithms that search for elements from the end
// of a range. They return a subrange from the found element to the end, or an
// empty subrange at the end if not found.
#include <iostream>
#include <algorithm>
#include <ranges>
#include <vector>
#include <string>
int main() {
std::vector<int> nums = {1, 3, 5, 3, 7, 3, 9, 2};
// ranges::find_last - find last occurrence of a value
std::cout << "=== find_last ===" << std::endl;
auto result = std::ranges::find_last(nums, 3);
if (!result.empty()) {
auto idx = result.begin() - nums.begin();
std::cout << " Last 3 found at index: " << idx << std::endl;
}
// Find last occurrence of a value not present
auto not_found = std::ranges::find_last(nums, 42);
std::cout << " 42 found: " << std::boolalpha << !not_found.empty() << std::endl;
// ranges::find_last_if - find last element matching a predicate
std::cout << "\n=== find_last_if ===" << std::endl;
auto last_even = std::ranges::find_last_if(nums, [](int n) { return n % 2 == 0; });
if (!last_even.empty()) {
auto idx = last_even.begin() - nums.begin();
std::cout << " Last even number: " << *last_even.begin()
<< " at index " << idx << std::endl;
}
auto last_gt5 = std::ranges::find_last_if(nums, [](int n) { return n > 5; });
if (!last_gt5.empty()) {
std::cout << " Last number > 5: " << *last_gt5.begin() << std::endl;
}
// ranges::find_last_if_not - find last element NOT matching a predicate
std::cout << "\n=== find_last_if_not ===" << std::endl;
auto last_not_odd = std::ranges::find_last_if_not(nums, [](int n) { return n % 2 != 0; });
if (!last_not_odd.empty()) {
auto idx = last_not_odd.begin() - nums.begin();
std::cout << " Last non-odd: " << *last_not_odd.begin()
<< " at index " << idx << std::endl;
}
// Practical: find last error in a log
std::vector<std::string> log = {
"INFO: start", "ERROR: disk full", "INFO: retry",
"ERROR: timeout", "INFO: recovered", "INFO: done"
};
std::cout << "\n=== Find last error in log ===" << std::endl;
auto last_error = std::ranges::find_last_if(log,
[](const std::string& s) { return s.starts_with("ERROR"); });
if (!last_error.empty()) {
auto idx = last_error.begin() - log.begin();
std::cout << " Last error at entry " << idx << ": "
<< *last_error.begin() << std::endl;
}
// Find last non-zero in data
std::vector<int> data = {5, 0, 3, 0, 0, 7, 0, 0};
auto last_nonzero = std::ranges::find_last_if(data, [](int n) { return n != 0; });
if (!last_nonzero.empty()) {
auto idx = last_nonzero.begin() - data.begin();
std::cout << "\n=== Last non-zero ===" << std::endl;
std::cout << " Value " << *last_nonzero.begin()
<< " at index " << idx << std::endl;
}
return 0;
}
// Expected output:
// === find_last ===
// Last 3 found at index: 5
// 42 found: false
//
// === find_last_if ===
// Last even number: 2 at index 7
// Last number > 5: 9
//
// === find_last_if_not ===
// Last non-odd: 2 at index 7
//
// === Find last error in log ===
// Last error at entry 3: ERROR: timeout
//
// === Last non-zero ===
// Value 7 at index 5
Run command
g++ -std=c++23 -Wall -Wextra -o example ranges_find_last.cpp