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