File indexing completed on 2024-05-05 04:38:42

0001 /*
0002     SPDX-FileCopyrightText: 2020 Igor Kushnir <igorkuo@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KDEVPLATFORM_ALGORITHM_H
0008 #define KDEVPLATFORM_ALGORITHM_H
0009 
0010 #include <QSet>
0011 
0012 #include <algorithm>
0013 #include <iterator>
0014 #include <type_traits>
0015 #include <vector>
0016 
0017 namespace Algorithm {
0018 /**
0019  * Computes the union of the QSet range [first, last) efficiently.
0020  *
0021  * @note Pass move iterators to this function if possible. Otherwise the largest set will be
0022  * detached and copied if there is more than one non-empty set in the range [first, last).
0023  */
0024 template <typename ForwardIt>
0025 auto unite(ForwardIt first, ForwardIt last)
0026 {
0027     if (first == last) {
0028         return std::remove_cv_t<std::remove_reference_t<decltype(*first)>>{};
0029     }
0030     const auto maxElement = std::max_element(first, last, [](const auto& a, const auto& b) {
0031         return a.size() < b.size();
0032     });
0033     Q_ASSERT(maxElement != last);
0034 
0035     // Start with the largest-size set. None of this set's elements is inserted
0036     // into another set, so picking the largest one achieves optimum performance.
0037     auto result = *maxElement;
0038     for ( ; first != maxElement; ++first) {
0039         result.unite(*first);
0040     }
0041     // skip the already included *maxElement
0042     for (++first; first != last; ++first) {
0043         result.unite(*first);
0044     }
0045     return result;
0046 }
0047 
0048 /**
0049  * This is an overloaded convenience function.
0050  */
0051 template <typename T>
0052 QSet<T> unite(std::vector<QSet<T>>&& sets)
0053 {
0054     return unite(std::make_move_iterator(sets.begin()),
0055                  std::make_move_iterator(sets.end()));
0056 }
0057 }
0058 
0059 #endif // KDEVPLATFORM_ALGORITHM_H