What STL algorithm can determine if exactly one item in a container satisfies a predicate?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In C++, the simplest way to check whether exactly one element matches a predicate is std::count_if combined with a comparison to one. This is clear and correct for most codebases. For large ranges, you can also use a short-circuit approach that stops once a second match is found.
Direct Solution with std::count_if
std::count_if scans the range and returns how many elements satisfy a predicate.
This is expressive and easy to read in code reviews.
C++20 Ranges Variant
If you use ranges, the same intent is even cleaner.
Choose this when your project already uses ranges heavily.
Early-Exit Approach for Performance-Sensitive Paths
count_if always scans the entire range. If matches are common and containers are large, you can stop early after finding a second match.
This can reduce work significantly when second matches appear early.
Generic Helper for Reuse
If the check appears often, wrap it in a utility helper to make intent obvious.
This keeps call sites concise and allows early exit.
Choosing Readability Versus Micro-Optimization
For most business applications, count_if == 1 is the best default. It is immediately understandable and less error-prone than custom loop logic.
Use early-exit helpers only when profiling shows this predicate check is on a hot path. Premature optimization can make code harder to maintain without measurable benefit.
If predicates are expensive, consider caching or precomputing classification values upstream rather than optimizing the matching loop alone.
Testing Strategy
Add tests for the three essential cases:
- No matches.
- Exactly one match.
- More than one match.
Also test empty containers and edge values. These tests prevent regression when predicates or data structures evolve.
Common Pitfalls
A common pitfall is using std::any_of and assuming it means exactly one. any_of checks one or more, not exactly one.
Another issue is writing custom loops without early-exit guard and accidentally counting all matches anyway. If you need performance, ensure loop logic returns as soon as the result is determined.
Developers also forget that predicate side effects can make behavior order-dependent. Keep predicates pure whenever possible.
Finally, mixing signed and unsigned counters in custom helpers can introduce subtle warnings or bugs. Use consistent types in reusable utilities.
Summary
- The standard answer is
std::count_if(...) == 1. std::ranges::count_ifoffers the same pattern in modern C++.- Use early-exit logic only when profiling justifies it in real workloads.
- Prefer pure predicates and explicit tests for zero, one, and many matches.
- Optimize for readability first, then tune proven hot paths.

