summaryrefslogtreecommitdiffstats
path: root/Source/cmAlgorithms.h
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2015-02-12 17:47:10 (GMT)
committerStephen Kelly <steveire@gmail.com>2015-02-15 18:04:31 (GMT)
commit0b5cf0dabd430dfe1289e865b1b51c41066338a7 (patch)
treecc48e846bf6269a9737f6267c7aae1fa5335dcf6 /Source/cmAlgorithms.h
parent069f2440c471e89dfe2ecf6778bbab16e9fbe491 (diff)
downloadCMake-0b5cf0dabd430dfe1289e865b1b51c41066338a7.zip
CMake-0b5cf0dabd430dfe1289e865b1b51c41066338a7.tar.gz
CMake-0b5cf0dabd430dfe1289e865b1b51c41066338a7.tar.bz2
cmAlgorithms: Implement algorithm for removing indexes.
Implement ContainerAlgorithms::RemoveN to remove N elements to the end of a container by rotating. The rotate is implemented in terms of the efficient swap algorithm, optimized even more in the standard library implementation when the compiler supports the rvalue-references feature to move elements. Implement cmRemoveN with a Range API for completeness. std::rotate in C++11 is specified to return an iterator, but c++98 specifies it to return void. libstdc++ 5.0 will be the first version to have the correct return type. Implement ContainerAlgorithms::Rotate in terms of std::rotate and return the correct iterator from it. While std::rotate requires forward iterators, this workaround means cmRotate requires bidirectional iterators. As most of CMake uses random access iterators anyway, this should not be a problem. Implement cmRemoveIndices in terms of the RemoveN algorithm, such that each element which is not removed is rotated only once. This can not use the cmRemoveN range-API algorithm because that would require creating a new range, but the range must be taken by reference and so it can't be a temporary. These remove algorithms are not part of the STL and I couldn't find them anywhere else either.
Diffstat (limited to 'Source/cmAlgorithms.h')
-rw-r--r--Source/cmAlgorithms.h38
1 files changed, 38 insertions, 0 deletions
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index ad2b9c1..70fdff6 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -138,6 +138,22 @@ private:
const_iterator End;
};
+template<typename BiDirIt>
+BiDirIt Rotate(BiDirIt first, BiDirIt middle, BiDirIt last)
+{
+ typename std::iterator_traits<BiDirIt>::difference_type dist =
+ std::distance(first, middle);
+ std::rotate(first, middle, last);
+ std::advance(last, -dist);
+ return last;
+}
+
+template<typename Iter>
+Iter RemoveN(Iter i1, Iter i2, size_t n)
+{
+ return ContainerAlgorithms::Rotate(i1, i1 + n, i2);
+}
+
}
template<typename Iter1, typename Iter2>
@@ -188,4 +204,26 @@ std::string cmJoin(Range const& r, std::string delimiter)
return cmJoin(r, delimiter.c_str());
};
+template<typename Range>
+typename Range::const_iterator cmRemoveN(Range& r, size_t n)
+{
+ return ContainerAlgorithms::RemoveN(r.begin(), r.end(), n);
+}
+
+template<typename Range, typename InputRange>
+typename Range::const_iterator cmRemoveIndices(Range& r, InputRange const& rem)
+{
+ typename InputRange::const_iterator remIt = rem.begin();
+
+ typename Range::iterator writer = r.begin() + *remIt;
+ ++remIt;
+ size_t count = 1;
+ for ( ; writer != r.end() && remIt != rem.end(); ++count, ++remIt)
+ {
+ writer = ContainerAlgorithms::RemoveN(writer, r.begin() + *remIt, count);
+ }
+ writer = ContainerAlgorithms::RemoveN(writer, r.end(), count);
+ return writer;
+}
+
#endif