diff options
author | Stephen Kelly <steveire@gmail.com> | 2015-02-12 18:47:10 +0100 |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2015-02-15 19:04:31 +0100 |
commit | 0b5cf0dabd430dfe1289e865b1b51c41066338a7 (patch) | |
tree | cc48e846bf6269a9737f6267c7aae1fa5335dcf6 /Source/cmAlgorithms.h | |
parent | 069f2440c471e89dfe2ecf6778bbab16e9fbe491 (diff) | |
download | cmake-0b5cf0dabd430dfe1289e865b1b51c41066338a7.tar.gz |
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.h | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index ad2b9c164e..70fdff69cd 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 |