summaryrefslogtreecommitdiffstats
path: root/Source/cmAlgorithms.h
diff options
context:
space:
mode:
authorArtur Ryt <artur.ryt@gmail.com>2019-03-03 13:19:18 (GMT)
committerBrad King <brad.king@kitware.com>2019-03-06 13:57:47 (GMT)
commitbf1e73305ac1b6bc9021b80fc8da99fda032c018 (patch)
treefa68fb2710bdcdecb01eb9b1069023d7fc564af0 /Source/cmAlgorithms.h
parent033728e86780d61215ebcab442d9a130bdd0461c (diff)
downloadCMake-bf1e73305ac1b6bc9021b80fc8da99fda032c018.zip
CMake-bf1e73305ac1b6bc9021b80fc8da99fda032c018.tar.gz
CMake-bf1e73305ac1b6bc9021b80fc8da99fda032c018.tar.bz2
cmAlgorithms: Refactor cmRemoveDuplicates
Use an iterator-based implementation with range-based one simply deferring to it. Also optimize a little by storing iterators to unique values to prevent creating value copies.
Diffstat (limited to 'Source/cmAlgorithms.h')
-rw-r--r--Source/cmAlgorithms.h54
1 files changed, 36 insertions, 18 deletions
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 2ff1ed0..0980416 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -233,27 +233,45 @@ typename Range::const_iterator cmRemoveMatching(Range& r, MatchRange const& m)
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
}
-template <typename Range>
-typename Range::const_iterator cmRemoveDuplicates(Range& r)
+template <typename ForwardIterator>
+ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last)
{
- typedef typename Range::value_type T;
- std::unordered_set<T> unique;
- std::vector<size_t> indices;
- size_t count = 0;
- const typename Range::const_iterator end = r.end();
- for (typename Range::const_iterator it = r.begin(); it != end;
- ++it, ++count) {
- const typename std::unordered_set<T>::iterator occur = unique.find(*it);
- if (occur == unique.end()) {
- unique.insert(*it);
- } else {
- indices.push_back(count);
+ using Value = typename std::iterator_traits<ForwardIterator>::value_type;
+ using Hash = struct
+ {
+ std::size_t operator()(ForwardIterator it) const
+ {
+ return std::hash<Value>{}(*it);
}
+ };
+
+ using Equal = struct
+ {
+ bool operator()(ForwardIterator it1, ForwardIterator it2) const
+ {
+ return *it1 == *it2;
+ }
+ };
+ std::unordered_set<ForwardIterator, Hash, Equal> uniq;
+
+ ForwardIterator result = first;
+ while (first != last) {
+ if (uniq.find(first) == uniq.end()) {
+ if (result != first) {
+ *result = std::move(*first);
+ }
+ uniq.insert(result);
+ ++result;
+ }
+ ++first;
}
- if (indices.empty()) {
- return end;
- }
- return cmRemoveIndices(r, indices);
+ return result;
+}
+
+template <typename Range>
+typename Range::const_iterator cmRemoveDuplicates(Range& r)
+{
+ return cmRemoveDuplicates(r.begin(), r.end());
}
template <typename Range>