Namespaces
Variants

std:: set_union

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Определено в заголовке <algorithm>
template < class InputIt1, class InputIt2, class OutputIt >

OutputIt set_union ( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,

OutputIt d_first ) ;
(1) (constexpr начиная с C++20)
template < class ExecutionPolicy,

class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 set_union ( ExecutionPolicy && policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,

ForwardIt3 d_first ) ;
(2) (начиная с C++17)
template < class InputIt1, class InputIt2,

class OutputIt, class Compare >
OutputIt set_union ( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,

OutputIt d_first, Compare comp ) ;
(3) (constexpr начиная с C++20)
template < class ExecutionPolicy,

class ForwardIt1, class ForwardIt2,
class ForwardIt3, class Compare >
ForwardIt3 set_union ( ExecutionPolicy && policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, ForwardIt2 last2,

ForwardIt3 d_first, Compare comp ) ;
(4) (начиная с C++17)

Создает отсортированное объединение, начинающееся с d_first , состоящее из набора элементов, присутствующих в одном или обоих отсортированных диапазонах [ first1 , last1 ) и [ first2 , last2 ) .

Если [ first1 , last1 ) содержит m эквивалентных элементов и [ first2 , last2 ) содержит n эквивалентных им элементов, то все m элементов будут скопированы из [ first1 , last1 ) в выходной диапазон с сохранением порядка, а затем последние std:: max ( n - m, 0 ) элементов будут скопированы из [ first2 , last2 ) в выходной диапазон, также с сохранением порядка.

1) Если [ first1 , last1 ) или [ first2 , last2 ) не является отсортированным относительно operator < (до C++20) std:: less { } (начиная с C++20) , поведение не определено.
3) Если [ first1 , last1 ) или [ first2 , last2 ) не отсортирован относительно comp , поведение не определено.
2,4) То же, что и (1,3) , но выполняется в соответствии с policy .
Эти перегрузки участвуют в разрешении перегрузки только при выполнении всех следующих условий:

std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> является true .

(до C++20)

std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> является true .

(начиная с C++20)

Если выходной диапазон пересекается с [ first1 , last1 ) или [ first2 , last2 ) , поведение не определено.

Содержание

Параметры

first1, last1 - пара итераторов, определяющая первый входной отсортированный диапазон элементов
first2, last2 - пара итераторов, определяющая второй входной отсортированный диапазон элементов
d_first - начало выходного диапазона
policy - политика выполнения, которую следует использовать
comp - функция сравнения (т.е. объект, удовлетворяющий требованиям Compare ), которая возвращает ​ true если первый аргумент меньше второго (т.е. упорядочен перед вторым).

Сигнатура функции сравнения должна быть эквивалентна следующей:

bool cmp ( const Type1 & a, const Type2 & b ) ;

Хотя сигнатура не обязана содержать const & , функция не должна модифицировать передаваемые ей объекты и должна быть способна принимать все значения типов (возможно, const) Type1 и Type2 независимо от категории значения (следовательно, Type1& не допускается , как и Type1 , если для Type1 перемещение не эквивалентно копированию (since C++11) ).
Типы Type1 и Type2 должны быть такими, чтобы объекты типов InputIt1 и InputIt2 могли быть разыменованы и неявно преобразованы как в Type1 , так и в Type2 . ​

Требования к типам
-
InputIt1, InputIt2 должны удовлетворять требованиям LegacyInputIterator .
-
ForwardIt1, ForwardIt2, ForwardIt3 должны удовлетворять требованиям LegacyForwardIterator .
-
OutputIt должны удовлетворять требованиям LegacyOutputIterator .
-
Compare должны удовлетворять требованиям Compare .

Возвращаемое значение

Итератор за концом построенного диапазона.

Сложность

Пусть N 1 равно std:: distance ( first1, last1 ) и N 2 равно std:: distance ( first2, last2 ) :

1,2) Не более 2⋅(N 1 +N 2 )-1 сравнений с использованием operator < (до C++20) std:: less { } (начиная с C++20) .
3,4) Не более 2⋅(N 1 +N 2 )-1 применений функции сравнения comp .

Исключения

Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:

  • Если выполнение функции, вызванной как часть алгоритма, выбрасывает исключение и ExecutionPolicy является одним из стандартных политик , std::terminate вызывается. Для любой другой ExecutionPolicy поведение определяется реализацией.
  • Если алгоритму не удается выделить память, std::bad_alloc выбрасывается.

Возможная реализация

set_union (1)
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt set_union(InputIt1 first1, InputIt1 last1,
                   InputIt2 first2, InputIt2 last2, OutputIt d_first)
{
    for (; first1 != last1; ++d_first)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        if (*first2 < *first1)
            *d_first = *first2++;
        else
        {
            *d_first = *first1;
            if (!(*first1 < *first2))
                ++first2;
            ++first1;
        }
    }
    return std::copy(first2, last2, d_first);
}
set_union (3)
template<class InputIt1, class InputIt2, class OutputIt, class Compare>
OutputIt set_union(InputIt1 first1, InputIt1 last1,
                   InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp)
{
    for (; first1 != last1; ++d_first)
    {
        if (first2 == last2)
            // Завершен диапазон 2, включаем оставшуюся часть диапазона 1:
            return std::copy(first1, last1, d_first);
        if (comp(*first2, *first1))
            *d_first = *first2++;
        else
        {
            *d_first = *first1;
            if (!comp(*first1, *first2)) // Эквивалентны => не нужно включать *first2.
                ++first2;
            ++first1;
        }
    }
    // Завершен диапазон 1, включаем оставшуюся часть диапазона 2:
    return std::copy(first2, last2, d_first);
}

Примечания

Этот алгоритм выполняет схожую задачу с std::merge . Оба обрабатывают два отсортированных входных диапазона и создают отсортированный выходной диапазон с элементами из обоих входов. Разница между этими двумя алгоритмами заключается в обработке значений из обоих входных диапазонов, которые сравниваются как эквивалентные (см. примечания по LessThanComparable ). Если любые эквивалентные значения появлялись n раз в первом диапазоне и m раз во втором, std::merge выведет все n + m вхождений, тогда как std::set_union выведет только std:: max ( n, m ) . Таким образом, std::merge выводит ровно std:: distance ( first1, last1 ) + std:: distance ( first2, last2 ) значений, а std::set_union может выдать меньше.

Пример

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
void println(const std::vector<int>& v)
{
    for (int i : v)
        std::cout << i << ' ';
    std::cout << '\n';
}
int main()
{
    std::vector<int> v1, v2, dest;
    v1 = {1, 2, 3, 4, 5};
    v2 = {3, 4, 5, 6, 7};
    std::set_union(v1.cbegin(), v1.cend(),
                   v2.cbegin(), v2.cend(),
                   std::back_inserter(dest));
    println(dest);
    dest.clear();
    v1 = {1, 2, 3, 4, 5, 5, 5};
    v2 = {3, 4, 5, 6, 7};
    std::set_union(v1.cbegin(), v1.cend(),
                   v2.cbegin(), v2.cend(),
                   std::back_inserter(dest));
    println(dest);
}

Вывод:

1 2 3 4 5 6 7 
1 2 3 4 5 5 5 6 7

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
LWG 291 C++98 не было указано, как обрабатывать эквивалентные элементы во входных диапазонах указано

Смотрите также

возвращает true если одна последовательность является подпоследовательностью другой
(шаблон функции)
объединяет два отсортированных диапазона
(шаблон функции)
вычисляет разность двух множеств
(шаблон функции)
вычисляет пересечение двух множеств
(шаблон функции)
вычисляет симметрическую разность двух множеств
(шаблон функции)
вычисляет объединение двух множеств
(функциональный объект алгоритма)