Чтобы добавить к предыдущим ответам - учтите, что сложность std::set_union
вдвое выше, чем std::merge
. На практике это означает, что компаратор в std::set_union
может быть применен к элементу после того, как был разыменован, в то время как с std::merge
это никогда не происходит.
Почему это может быть важно? Рассмотрим что-то вроде:
std::vector<Foo> lhs, rhs;
И вы хотите создать объединение lhs
и rhs
:
std::set_union(std::cbegin(lhs), std::cend(lhs),
std::cbegin(rhs), std::cend(rhs),
std::back_inserter(union));
Но теперь предположим, что Foo
не подлежит копированию или копирование очень дорого, и вам не нужны оригиналы. Вы можете подумать использовать:
std::set_union(std::make_move_iterator(std::begin(lhs)),
std::make_move_iterator(std::end(lhs)),
std::make_move_iterator(std::begin(rhs)),
std::make_move_iterator(std::end(rhs)),
std::back_inserter(union));
Но это неопределенное поведение, так как существует вероятность сравнения перемещенного Foo
! Следовательно, правильное решение:
std::merge(std::make_move_iterator(std::begin(lhs)),
std::make_move_iterator(std::end(lhs)),
std::make_move_iterator(std::begin(rhs)),
std::make_move_iterator(std::end(rhs)),
std::back_inserter(union));
union.erase(std::unique(std::begin(union), std::end(union), std::end(union));
Имеет ту же сложность, что и std::set_union
.