Here is another alternative using callbacks for maximum flexibility.
template <class Input1, class Input2 , class FuncAdd, class FuncRm, class FuncSame, class Comp> void set_difference_adv(Input1 firstOld, Input1 lastOld ,Input2 firstNew, Input2 lastNew ,FuncAdd onadded, FuncRm onremoved, FuncSame onsame, Comp comp) { while (firstOld != lastOld && firstNew != lastNew) { if (comp(*firstOld, *firstNew)) { onremoved(*firstOld++); } else if (comp(*firstNew, *firstOld)) { onadded(*firstNew++); } else { onsame(*firstOld++, *firstNew++); } } std::for_each(firstOld, lastOld, onremoved); std::for_each(firstNew, lastNew, onadded); }
This has the following advantages:
- Output Lists Now Optional
- The output may be of another type (conversion)
- Common elements can be further processed in tandem (additional comparison)
Real World Example:
int main() { using File = std::pair<std::string, int>; std::vector<File> files1{{"file1", 12}, {"file3", 8}, {"file4", 2}, {"file5", 10}}; std::vector<File> files2{{"file1", 12}, {"file2", 5}, {"file3", 8}, {"file4", 33}}; const auto less = [](const auto& o, const auto& n) { return o.first < n.first; }; std::vector<std::string> addedNames; std::vector<File> changedFiles; set_difference_adv(std::cbegin(files1), std::cend(files1) ,std::cbegin(files2), std::cend(files2) , [&addedNames](const auto& val){ addedNames.push_back(val.first); }