Port some existing cmJoin to use it.
cmJoin is cumbersome to use in cases where the objective is to
somehow 'quote' each item and then join it with a separator. In that
case, the joiner string is harder to read and reason about. cmWrap
aims to solve that.
Provide an overload taking char wrappers to simplify the case
of surrounding every element in quotes without needing to escape
the quote character.
Start by creating a vector to hold a unique values of the input range. We
expect that in most cases, there will be relatively few duplicates, so
reserving enough memory for a complete copy is worthwhile. Unlike a solution
involving a std::set, this algorithm allocates all the memory it needs
in one go and in one place, so it is more cache friendly.
Populate the unique copy with a lower_bound insert algorithm and record the
indices of duplicates. This is the same complexity as the std::set insert
algorithm, but without the need to allocate memory on the heap and other
disadvantages of std::set.
Remove the duplicates with the cmRemoveIndices algorithm.
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.
This can make a pair of iterators API compatible with the
cmJoin algorithm and other range-based algorithms.
Accept different iterator types in the cmRange adaptor so that
a const and non-const iterator are accepted.