```cpp
    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`).

```cpp
                *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.

```cpp
    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;
    }
```