How it works...

All the set operations that produce a new range from two input ranges, in fact, have the same interface and work in a similar way:

  • They take two input ranges, each defined by a first and last input iterator.
  • They take an output iterator to an output range where elements will be inserted.
  • They have an overload that takes an extra argument representing a comparison binary function object that must return true if the first argument is less than the second. When a comparison function object is not specified, operator< is used.
  • They return an iterator past the end of the constructed output range.
  • The input ranges must be sorted using either operator< or the provided comparison function, depending on the overload that is used.
  • The output range must not overlap any of the two input ranges.

We will demonstrate the way they work with additional examples using vectors of a POD type Task that we also used in a previous recipe:

    struct Task
{
int priority;
std::string name;
};

bool operator<(Task const & lhs, Task const & rhs) {
return lhs.priority < rhs.priority;
}

bool operator>(Task const & lhs, Task const & rhs) {
return lhs.priority > rhs.priority;
}

std::vector<Task> v1{
{ 10, "Task 1.1"s },
{ 20, "Task 1.2"s },
{ 20, "Task 1.3"s },
{ 20, "Task 1.4"s },
{ 30, "Task 1.5"s },
{ 50, "Task 1.6"s },
};

std::vector<Task> v2{
{ 20, "Task 2.1"s },
{ 30, "Task 2.2"s },
{ 30, "Task 2.3"s },
{ 30, "Task 2.4"s },
{ 40, "Task 2.5"s },
{ 50, "Task 2.6"s },
};

The particular way each algorithm produces the output range is described here:

  • std::set_union() copies all the elements present in one or both of the input ranges to the output range, producing a new sorted range. If an element is found M times in the first range and N times in the second range, then all the M elements from the first range will be copied to the output range in their existing order, and then the N-M elements from the second range are copied to the output range if N > M, or 0 elements otherwise:
        std::vector<Task> v3;
std::set_union(v1.cbegin(), v1.cend(),
v2.cbegin(), v2.cend(),
std::back_inserter(v3));
// v3 = {{10, "Task 1.1"},{20, "Task 1.2"},{20, "Task 1.3"},
// {20, "Task 1.4"},{30, "Task 1.5"},{30, "Task 2.3"},
// {30, "Task 2.4"},{40, "Task 2.5"},{50, "Task 1.6"}}
  • std::merge() copies all the elements from both the input ranges into the output range, producing a new range sorted with respect to the comparison function:
        std::vector<Task> v4;
std::merge(v1.cbegin(), v1.cend(),
v2.cbegin(), v2.cend(),
std::back_inserter(v4));
// v4 = {{10, "Task 1.1"},{20, "Task 1.2"},{20, "Task 1.3"},
// {20, "Task 1.4"},{20, "Task 2.1"},{30, "Task 1.5"},
// {30, "Task 2.2"},{30, "Task 2.3"},{30, "Task 2.4"},
// {40, "Task 2.5"},{50, "Task 1.6"},{50, "Task 2.6"}}
  • std::set_intersection() copies all the elements that are found in both the input ranges into the output range, producing a new range sorted with respect to the comparison function:
        std::vector<Task> v5;
std::set_intersection(v1.cbegin(), v1.cend(),
v2.cbegin(), v2.cend(),
std::back_inserter(v5));
// v5 = {{20, "Task 1.2"},{30, "Task 1.5"},{50, "Task 1.6"}}
  • std::set_difference() copies to the output range all the elements from the first input range that are not found in the second input range. For equivalent elements that are found in both the ranges, the following rule applies: if an element is found M times in the first range and N times in the second range, and if M > N, then it is copied M-N times; otherwise it is not copied:
        std::vector<Task> v6;
std::set_difference(v1.cbegin(), v1.cend(),
v2.cbegin(), v2.cend(),
std::back_inserter(v6));
// v6 = {{10, "Task 1.1"},{20, "Task 1.3"},{20, "Task 1.4"}}
  • std::set_symmetric_difference() copies to the output range all the elements that are found in either of the two input ranges but not in both of them. If an element is found M times in the first range and N times in the second range, then if M > N, the last M-N of those elements from the first range are copied into the output rage, else, the last N-M of those elements from the second range will be copied into the output range:
        std::vector<Task> v7;
std::set_symmetric_difference(v1.cbegin(), v1.cend(),
v2.cbegin(), v2.cend(),
std::back_inserter(v7));
// v7 = {{10, "Task 1.1"},{20, "Task 1.3"},{20, "Task 1.4"}
// {30, "Task 2.3"},{30, "Task 2.4"},{40, "Task 2.5"}}

On the other hand, std::includes() does not produce an output range; it only checks whether the second range is included in the first range. It returns a Boolean value that is true if the second range is empty or all its elements are included in the first range, or false otherwise. It also has two overloads, one of them specifying a comparison binary function object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset