while (first < last)
{
std::pop_heap(first, last--, comp);
auto y = *last;
if (first < last) {
- If you know the distance from
first
to last
is at least \$2\$, you don't need the inner check. For range distances of \$2\$ or greater, you always pop twice and maybe push. When the distance is less than \$2\$, either the final stone exists at first
(first < last
) or is \$0\$ (first == last
).
*last = y - x;
y - x
works fine if the comparator is std::less<>
. What happens when the comparator switches to std::greater<>
? The ordering changes. y
would be the smaller value, so y-x
would produce a negative value for signed numeric types and underflow for unsigned numeric types. If you want to support comparators, you should provide a difference function to ensure the ordering is applied correctly.
template<class Iterator>
typename Iterator::value_type stone_smash_destructive(Iterator first, Iterator last)
{
std::make_heap(first, last);
while (last - first > 1)
{
std::pop_heap(first, last--);
auto first_popped = *last;
std::pop_heap(first, last--);
auto second_popped = *last;
if (second_popped < first_popped)
{
*last = first_popped - second_popped;
std::push_heap(first, ++last);
}
}
if (first == last) {
return {0};
}
return *first;
}
```