We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Containers, Strings, Algorithms step 4 of 5
The loop stops having bugs once it has a name
The argument for <algorithm> is usually made about brevity, and brevity is
the least of it. The real argument is that a hand-written loop has places for
bugs to live and a named algorithm does not.
int best = 0; // <- here
for (std::size_t i = 0; i < values.size(); ++i) { // <- and here
if (values[i] > best) { // <- and here
best = values[i];
}
}
Three lines, three classic defects: the accumulator initialised to a value
that is not in the data, the index arithmetic, and the comparison that
decides ties. std::ranges::max_element(values) has none of them, and it
also forces you to answer the question the loop above silently got wrong —
what is the maximum of an empty range? — because it hands you end() and
makes you say.
The ones worth knowing by name
max_element / min_element |
an iterator to the largest / smallest |
find / find_if |
the first match, or end() |
count / count_if |
how many |
any_of / all_of / none_of |
a question, answered as a bool |
accumulate (in <numeric>) |
a fold |
sort / stable_sort / partial_sort |
ordering, with a choice about ties |
transform |
element-wise mapping |
remove_if + erase |
filtering in place — Track 5.5 |
Each of these turns a shape you would have to read into a word you can
recognise. A reviewer skimming std::ranges::any_of(users, is_admin) is done
in a second; the same thing spelled as a loop with an early return true
needs actual reading.
Two forms
C++20 added range overloads that take the container itself:
std::ranges::max_element(values); // preferred
std::max_element(values.begin(), values.end()); // the older form
Same algorithm. The range form cannot be given two iterators from different
containers, which is a real class of bug removed. clang-tidy’s
modernize-use-ranges will ask you for it, and the gate enforces that.
A few things still have no range form in C++20 — std::accumulate is the one
you will meet first — so the iterator pair is not obsolete.
accumulate and its initial value
std::accumulate(v.begin(), v.end(), 0); // sums as int
std::accumulate(v.begin(), v.end(), 0LL); // sums as long long
The accumulator’s type comes from the initial value, not from the
elements. A vector of int summed with 0 overflows exactly as a plain
int would, which is a bug you cannot see at the call site unless you know
this rule.
Your task
std::vector<long long> summarize(const std::vector<int>& values, int threshold);
Return four numbers, in this order:
-
the largest value, or
0ifvaluesis empty; -
the index of the first value strictly greater than
threshold, or-1if there is none; -
how many values are strictly greater than
threshold; -
the sum of every value, as a
long long.
The starter does all four by hand and gets two of them wrong. Both mistakes are the kind that a named algorithm does not have room for.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.