One alternative to separate "destructive" and "copying" functions that I've used successfully in the past is to accept the collection by value. Then a caller can use std::move()
to avoid copying elements when they do not need to be preserved.
Modified code
CorrectedOne alternative to separate "destructive" and simplified"copying" functions that I've used successfully in the past is to accept the collection by value. Then a caller can use std::move()
to avoid copying elements when they do not need to be preserved.
That might look like this:
#include <algorithm>
#include <concepts>
#include <functional>
#include <vector><ranges>
template<classtemplate<std::ranges::bidirectional_range IteratorContainer,
class Compare>
typename Iterator std::value_typepredicate<std::ranges::range_value_t<Container>, stone_smash_destructivestd::ranges::range_value_t<Container>> Compare>
auto stone_smash(IteratorContainer firstvalues, IteratorCompare last,comp = std::less<>{})
{
auto const first = values.begin();
auto last = values.end();
⋮
return std::ranges::range_value_t<Container>{};
}
And we'd call it slightly differently:
assert(expected == stone_smash(v, comp));
assert(expected == stone_smash(std::move(v), comp));
Or we can call it destructively from an iterator pair by constructing a std::range::subrange
from them.
Modified code
Corrected and simplified:
#include <algorithm>
#include <concepts>
#include <functional>
#include <ranges>
template<std::ranges::bidirectional_range Container,
std::predicate<std::ranges::range_value_t<Container>, std::ranges::range_value_t<Container>> Compare>
auto stone_smash(Container values, Compare comp = std::less<>{})
{
auto const first = values.begin();
auto last = values.end();
std::make_heap(first, last, comp);
while (first < last)
{
std::pop_heap(first, last--, comp);
if (first == last) {
return *first;
}
auto const y = *last;
std::pop_heap(first, last--, comp);
auto const x = *last;
if (comp(x, y)) {
*last = y - x;
std::push_heap(first, ++last, comp);
}
}
return {0};
}
template<class Iterator, class Compare>
typename Iteratorstd::value_type stone_smash(Iterator first, Iterator last,
Compare comp = stdranges::less<>range_value_t<Container>{})
{
auto v = std::vector(first, last);
return stone_smash_destructive(v.begin(), v.end(), comp);
}