mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00

#pragma once is a widely supported compiler pragma, even though it is not part of the C++ standard. Many of the issues keeping #pragma once from being standardized (distributed filesystems, build farms, hard links, etc.) do not apply to CMake - it is easy to build CMake on a single machine. CMake also does not install any header files which can be consumed by other projects (though cmCPluginAPI.h has been deliberately omitted from this conversion in case anyone is still using it.) Finally, #pragma once has been required to build CMake since at least August 2017 (7f29bbe6
enabled server mode unconditionally, which had been using #pragma once since September 2016 (b13d3e0d
)). The fact that we now require C++11 filters out old compilers, and it is unlikely that there is a compiler which supports C++11 but does not support #pragma once.
145 lines
3.5 KiB
C++
145 lines
3.5 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
#pragma once
|
|
|
|
#include "cmConfigure.h" // IWYU pragma: keep
|
|
|
|
#include <algorithm>
|
|
#include <functional>
|
|
#include <iterator>
|
|
#include <memory>
|
|
#include <unordered_set>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <cmext/algorithm>
|
|
|
|
#include "cmRange.h"
|
|
|
|
template <typename FwdIt>
|
|
FwdIt cmRotate(FwdIt first, FwdIt middle, FwdIt last)
|
|
{
|
|
const typename std::iterator_traits<FwdIt>::difference_type dist =
|
|
std::distance(middle, last);
|
|
std::rotate(first, middle, last);
|
|
std::advance(first, dist);
|
|
return first;
|
|
}
|
|
|
|
namespace ContainerAlgorithms {
|
|
|
|
template <typename FwdIt>
|
|
FwdIt RemoveN(FwdIt i1, FwdIt i2, size_t n)
|
|
{
|
|
FwdIt m = i1;
|
|
std::advance(m, n);
|
|
return cmRotate(i1, m, i2);
|
|
}
|
|
|
|
template <typename Range>
|
|
struct BinarySearcher
|
|
{
|
|
using argument_type = typename Range::value_type;
|
|
BinarySearcher(Range const& r)
|
|
: m_range(r)
|
|
{
|
|
}
|
|
|
|
bool operator()(argument_type const& item) const
|
|
{
|
|
return std::binary_search(m_range.begin(), m_range.end(), item);
|
|
}
|
|
|
|
private:
|
|
Range const& m_range;
|
|
};
|
|
}
|
|
|
|
class cmListFileBacktrace;
|
|
using cmBacktraceRange =
|
|
cmRange<std::vector<cmListFileBacktrace>::const_iterator>;
|
|
|
|
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 InputRange::const_iterator remEnd = rem.end();
|
|
const auto rangeEnd = r.end();
|
|
if (remIt == remEnd) {
|
|
return rangeEnd;
|
|
}
|
|
|
|
auto writer = r.begin();
|
|
std::advance(writer, *remIt);
|
|
auto pivot = writer;
|
|
typename InputRange::value_type prevRem = *remIt;
|
|
++remIt;
|
|
size_t count = 1;
|
|
for (; writer != rangeEnd && remIt != remEnd; ++count, ++remIt) {
|
|
std::advance(pivot, *remIt - prevRem);
|
|
prevRem = *remIt;
|
|
writer = ContainerAlgorithms::RemoveN(writer, pivot, count);
|
|
}
|
|
return ContainerAlgorithms::RemoveN(writer, rangeEnd, count);
|
|
}
|
|
|
|
template <typename Range, typename MatchRange>
|
|
typename Range::const_iterator cmRemoveMatching(Range& r, MatchRange const& m)
|
|
{
|
|
return std::remove_if(r.begin(), r.end(),
|
|
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
|
|
}
|
|
|
|
template <typename ForwardIterator>
|
|
ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last)
|
|
{
|
|
using Value = typename std::iterator_traits<ForwardIterator>::value_type;
|
|
struct Hash
|
|
{
|
|
std::size_t operator()(ForwardIterator it) const
|
|
{
|
|
return std::hash<Value>{}(*it);
|
|
}
|
|
};
|
|
|
|
struct Equal
|
|
{
|
|
bool operator()(ForwardIterator it1, ForwardIterator it2) const
|
|
{
|
|
return *it1 == *it2;
|
|
}
|
|
};
|
|
std::unordered_set<ForwardIterator, Hash, Equal> uniq;
|
|
|
|
ForwardIterator result = first;
|
|
while (first != last) {
|
|
if (!cm::contains(uniq, first)) {
|
|
if (result != first) {
|
|
*result = std::move(*first);
|
|
}
|
|
uniq.insert(result);
|
|
++result;
|
|
}
|
|
++first;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template <typename Range>
|
|
typename Range::const_iterator cmRemoveDuplicates(Range& r)
|
|
{
|
|
return cmRemoveDuplicates(r.begin(), r.end());
|
|
}
|
|
|
|
template <typename Range, typename T>
|
|
typename Range::const_iterator cmFindNot(Range const& r, T const& t)
|
|
{
|
|
return std::find_if(r.begin(), r.end(), [&t](T const& i) { return i != t; });
|
|
}
|