Inplace versions of set_difference, set_intersection and set_union

Viewed 708

I implemented versions of set_union, set_intersection and set_difference that take a sorted container and a sorted range (that must not be within the container), and write the result of the operation into the container.

template<class Container, class Iter>
void assign_difference(Container& cont, Iter first, Iter last)
{
    auto new_end = std::set_difference( // (1)
        cont.begin(), cont.end(), first, last, cont.begin());
    cont.erase(new_end, cont.end());
}

template<class Container, class Iter>
void assign_intersection(Container& cont, Iter first, Iter last)
{
    auto new_end = std::set_intersection( // (2)
        cont.begin(), cont.end(), first, last, cont.begin());
    cont.erase(new_end, cont.end());
}

template<class Container, class Iter>
void assign_union(Container& cont, Iter first, Iter last)
{
    auto insert_count = last - first;
    cont.resize(cont.size() + insert_count); // T must be default-constructible
    auto rfirst1 = cont.rbegin() + insert_count, rlast1 = cont.rend();
    auto rfirst2 = std::make_reverse_iterator(last);
    auto rlast2 = std::make_reverse_iterator(first);
    rlast1 = std::set_union( // (3)
        rfirst1, rlast1, rfirst2, rlast2, cont.rbegin(), std::greater<>());
    cont.erase(std::copy(rlast1.base(), cont.end(), cont.begin()), cont.end());
}

The goal was:

  • No allocation is performed if the container has enaugh capacity to hold the result.
  • Otherwise exactly one allocation is performed to give the container the capacity to hold the result.

As you can see in the lines marked (1), (2) and (3), the same container is used as input and output for those STL algorithms. Assuming a usual implementation of those STL algorithms, this code works, since it only writes to parts of the container that have already been processed.

As pointed out in the comments, it's not guaranteed by the standard that this works. set_union, set_intersection and set_difference require that the resulting range doesn't overlap with one of the input ranges. However, can there be a STL implementation that breaks the code?

If your answer is yes, please provide a conforming implementations of one of the three used STL algorithms that breaks the code.

2 Answers
Related