summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2019-02-25 13:00:15 +0000
committerKitware Robot <kwrobot@kitware.com>2019-02-25 08:03:01 -0500
commita4d99e4dec6818406ef0c09c456a9dd08fb8c384 (patch)
tree8bfb36d98c2b0b1bc770a22ea5b0d20dedf46efa
parent94970cd042963bedd4594d867802880b13fa9f69 (diff)
parentb8031308f39d66d0dca3b5c59fe62805298dc91f (diff)
downloadcmake-a4d99e4dec6818406ef0c09c456a9dd08fb8c384.tar.gz
Merge topic 'cmrange-improvements'
b8031308f3 cmRange: Add unit tests a8d51ef8b7 cmRange: Add functions filter and transform da4773e8b8 cmRange: Add functions all_of, any_of, none_of 17a367e77f cmRange: Stylistic cleanup 9eb0e73f46 cmRange: Move to dedicated header file Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Artur Ryt <artur.ryt@gmail.com> Merge-request: !2972
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx2
-rw-r--r--Source/CTest/cmCTestP4.cxx2
-rw-r--r--Source/cmAddDependenciesCommand.cxx2
-rw-r--r--Source/cmAddSubDirectoryCommand.cxx2
-rw-r--r--Source/cmAlgorithms.h67
-rw-r--r--Source/cmComputeLinkDepends.cxx1
-rw-r--r--Source/cmComputeTargetDepends.cxx2
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx1
-rw-r--r--Source/cmFLTKWrapUICommand.cxx2
-rw-r--r--Source/cmFileCommand.cxx1
-rw-r--r--Source/cmFindBase.cxx1
-rw-r--r--Source/cmFindPackageCommand.cxx1
-rw-r--r--Source/cmForEachCommand.cxx1
-rw-r--r--Source/cmFunctionCommand.cxx1
-rw-r--r--Source/cmGeneratorTarget.cxx1
-rw-r--r--Source/cmGlobalGenerator.cxx1
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx1
-rw-r--r--Source/cmInstallCommandArguments.cxx2
-rw-r--r--Source/cmInstallFilesCommand.cxx2
-rw-r--r--Source/cmListCommand.cxx1
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx1
-rw-r--r--Source/cmMacroCommand.cxx1
-rw-r--r--Source/cmMakefile.cxx1
-rw-r--r--Source/cmMakefileTargetGenerator.cxx1
-rw-r--r--Source/cmMessageCommand.cxx1
-rw-r--r--Source/cmParseArgumentsCommand.cxx1
-rw-r--r--Source/cmQTWrapCPPCommand.cxx2
-rw-r--r--Source/cmQTWrapUICommand.cxx2
-rw-r--r--Source/cmRST.cxx1
-rw-r--r--Source/cmRange.h239
-rw-r--r--Source/cmSetCommand.cxx1
-rw-r--r--Source/cmSetPropertyCommand.cxx2
-rw-r--r--Source/cmStateDirectory.cxx1
-rw-r--r--Source/cmStringCommand.cxx1
-rw-r--r--Source/cmSystemTools.cxx1
-rw-r--r--Source/cmTarget.cxx1
-rw-r--r--Source/cmTestGenerator.cxx2
-rw-r--r--Source/cmTryRunCommand.cxx2
-rw-r--r--Source/cmcmd.cxx1
-rw-r--r--Tests/CMakeLib/CMakeLists.txt1
-rw-r--r--Tests/CMakeLib/testRange.cxx45
41 files changed, 324 insertions, 78 deletions
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 1c16a712f4..477161abb4 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -3,12 +3,12 @@
#include "cmCTestMultiProcessHandler.h"
#include "cmAffinity.h"
-#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestRunTest.h"
#include "cmCTestTestHandler.h"
#include "cmDuration.h"
#include "cmListFileCache.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
diff --git a/Source/CTest/cmCTestP4.cxx b/Source/CTest/cmCTestP4.cxx
index 315f49855a..7adf640130 100644
--- a/Source/CTest/cmCTestP4.cxx
+++ b/Source/CTest/cmCTestP4.cxx
@@ -2,10 +2,10 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestP4.h"
-#include "cmAlgorithms.h"
#include "cmCTest.h"
#include "cmCTestVC.h"
#include "cmProcessTools.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
#include "cmsys/RegularExpression.hxx"
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index 102380862f..4956a471c2 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -4,9 +4,9 @@
#include <sstream>
-#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmTarget.h"
class cmExecutionStatus;
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index c47092abd4..7947188a58 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -5,8 +5,8 @@
#include <sstream>
#include <string.h>
-#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 1c4160b1d5..2ff1ed0408 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -5,6 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmRange.h"
+
#include "cm_kwiml.h"
#include <algorithm>
#include <functional>
@@ -156,69 +158,12 @@ private:
};
}
-template <typename const_iterator_>
-struct cmRange
-{
- typedef const_iterator_ const_iterator;
- typedef typename std::iterator_traits<const_iterator>::value_type value_type;
- typedef typename std::iterator_traits<const_iterator>::difference_type
- difference_type;
- cmRange(const_iterator begin_, const_iterator end_)
- : Begin(begin_)
- , End(end_)
- {
- }
- const_iterator begin() const { return Begin; }
- const_iterator end() const { return End; }
- bool empty() const { return std::distance(Begin, End) == 0; }
- difference_type size() const { return std::distance(Begin, End); }
-
- cmRange& advance(KWIML_INT_intptr_t amount) &
- {
- std::advance(this->Begin, amount);
- return *this;
- }
- cmRange advance(KWIML_INT_intptr_t amount) &&
- {
- std::advance(this->Begin, amount);
- return std::move(*this);
- }
-
- cmRange& retreat(KWIML_INT_intptr_t amount) &
- {
- std::advance(End, -amount);
- return *this;
- }
-
- cmRange retreat(KWIML_INT_intptr_t amount) &&
- {
- std::advance(End, -amount);
- return std::move(*this);
- }
-
-private:
- const_iterator Begin;
- const_iterator End;
-};
-
typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange;
class cmListFileBacktrace;
typedef cmRange<std::vector<cmListFileBacktrace>::const_iterator>
cmBacktraceRange;
-template <typename Iter1, typename Iter2>
-cmRange<Iter1> cmMakeRange(Iter1 begin, Iter2 end)
-{
- return cmRange<Iter1>(begin, end);
-}
-
-template <typename Range>
-cmRange<typename Range::const_iterator> cmMakeRange(Range const& range)
-{
- return cmRange<typename Range::const_iterator>(range.begin(), range.end());
-}
-
template <typename Range>
void cmDeleteAll(Range const& r)
{
@@ -334,14 +279,6 @@ 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; });
}
-template <typename Range>
-cmRange<typename Range::const_reverse_iterator> cmReverseRange(
- Range const& range)
-{
- return cmRange<typename Range::const_reverse_iterator>(range.rbegin(),
- range.rend());
-}
-
template <class Iter>
std::reverse_iterator<Iter> cmMakeReverseIterator(Iter it)
{
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 5ed6c29b7b..186deb60cc 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -9,6 +9,7 @@
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 70d167553a..01d4c07e02 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmComputeTargetDepends.h"
-#include "cmAlgorithms.h"
#include "cmComputeComponentGraph.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -12,6 +11,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 9e90547b4c..93ff8f4d54 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -13,6 +13,7 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index 1b509efcd8..89629c7686 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -4,9 +4,9 @@
#include <stddef.h>
-#include "cmAlgorithms.h"
#include "cmCustomCommandLines.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 96c9e15127..59ef48d99a 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -34,6 +34,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cm_sys_stat.h"
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index f92f66e239..2e5e29cf3f 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -9,6 +9,7 @@
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 0d22ed8e77..7ebd211621 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -23,6 +23,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 39430d0c13..08003eb71d 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -11,6 +11,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
cmForEachFunctionBlocker::cmForEachFunctionBlocker(cmMakefile* mf)
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 264a3385cb..9d75b721c3 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -8,6 +8,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmState.h"
// define the class for function commands
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 3f23e5aaf4..624333c2ab 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -28,6 +28,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPropertyMap.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmState.h"
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index ab8d6701a6..57cb997187 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -35,6 +35,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index b78ffa90d2..018606cfd3 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -26,6 +26,7 @@
#include "cmMessageType.h"
#include "cmNinjaLinkLineComputer.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 647c786e2b..c64bd8a64d 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -2,7 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallCommandArguments.h"
-#include "cmAlgorithms.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
#include <utility>
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 1b72ce6289..b068e46c7a 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -2,12 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmInstallFilesCommand.h"
-#include "cmAlgorithms.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallGenerator.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index fdbd5baa31..5474afae4a 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -19,6 +19,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index f8e74415af..33a31ddce1 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -22,6 +22,7 @@
#include "cmMakefile.h"
#include "cmMakefileTargetGenerator.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 7279d5fcf8..6565f02602 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -10,6 +10,7 @@
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmSystemTools.h"
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f66999f440..04171e8a41 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -31,6 +31,7 @@
#include "cmInstallSubdirectoryGenerator.h"
#include "cmListFileCache.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmState.h"
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index cb595fdb4b..340e405705 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmMakefileLibraryTargetGenerator.h"
#include "cmMakefileUtilityTargetGenerator.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 1a21ae41bb..2724030c24 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -6,6 +6,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmMessenger.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 6231aab03e..ab8d1039b3 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -10,6 +10,7 @@
#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
class cmExecutionStatus;
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index 8b42119437..9a764c6780 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -2,9 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQTWrapCPPCommand.h"
-#include "cmAlgorithms.h"
#include "cmCustomCommandLines.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index 6a620c11c5..2223e2d825 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -2,9 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQTWrapUICommand.h"
-#include "cmAlgorithms.h"
#include "cmCustomCommandLines.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
diff --git a/Source/cmRST.cxx b/Source/cmRST.cxx
index 55204d708e..5917e27337 100644
--- a/Source/cmRST.cxx
+++ b/Source/cmRST.cxx
@@ -3,6 +3,7 @@
#include "cmRST.h"
#include "cmAlgorithms.h"
+#include "cmRange.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
diff --git a/Source/cmRange.h b/Source/cmRange.h
new file mode 100644
index 0000000000..3be5193e79
--- /dev/null
+++ b/Source/cmRange.h
@@ -0,0 +1,239 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmRange_h
+#define cmRange_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+
+namespace RangeIterators {
+
+template <typename Iter, typename UnaryPredicate>
+class FilterIterator
+{
+public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = typename std::iterator_traits<Iter>::value_type;
+ using difference_type = typename std::iterator_traits<Iter>::difference_type;
+ using pointer = typename std::iterator_traits<Iter>::pointer;
+ using reference = typename std::iterator_traits<Iter>::reference;
+
+ FilterIterator(Iter b, Iter e, UnaryPredicate p)
+ : Cur(std::move(b))
+ , End(std::move(e))
+ , Pred(std::move(p))
+ {
+ this->SatisfyPredicate();
+ }
+
+ FilterIterator& operator++()
+ {
+ ++this->Cur;
+ this->SatisfyPredicate();
+ return *this;
+ }
+
+ FilterIterator& operator--()
+ {
+ do {
+ --this->Cur;
+ } while (!this->Pred(*this->Cur));
+ return *this;
+ }
+
+ bool operator==(FilterIterator const& other) const
+ {
+ return this->Cur == other.Cur;
+ }
+
+ bool operator!=(FilterIterator const& other) const
+ {
+ return !this->operator==(other);
+ }
+
+ auto operator*() const -> decltype(*std::declval<Iter>())
+ {
+ return *this->Cur;
+ }
+
+private:
+ void SatisfyPredicate()
+ {
+ while (this->Cur != this->End && !this->Pred(*this->Cur)) {
+ ++this->Cur;
+ }
+ }
+
+ Iter Cur;
+ Iter End;
+ UnaryPredicate Pred;
+};
+
+template <typename Iter, typename UnaryFunction>
+class TransformIterator
+{
+public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type =
+ typename std::remove_cv<typename std::remove_reference<decltype(
+ std::declval<UnaryFunction>()(*std::declval<Iter>()))>::type>::type;
+ using difference_type = typename std::iterator_traits<Iter>::difference_type;
+ using pointer = value_type const*;
+ using reference = value_type const&;
+
+ TransformIterator(Iter i, UnaryFunction f)
+ : Base(std::move(i))
+ , Func(std::move(f))
+ {
+ }
+
+ TransformIterator& operator++()
+ {
+ ++this->Base;
+ return *this;
+ }
+
+ TransformIterator& operator--()
+ {
+ --this->Base;
+ return *this;
+ }
+
+ bool operator==(TransformIterator const& other) const
+ {
+ return this->Base == other.Base;
+ }
+
+ bool operator!=(TransformIterator const& other) const
+ {
+ return !this->operator==(other);
+ }
+
+ auto operator*() const
+ -> decltype(std::declval<UnaryFunction>()(*std::declval<Iter>()))
+ {
+ return this->Func(*this->Base);
+ }
+
+private:
+ Iter Base;
+ UnaryFunction Func;
+};
+
+} // namespace RangeIterators
+
+template <typename Iter>
+class cmRange
+{
+public:
+ using const_iterator = Iter;
+ using value_type = typename std::iterator_traits<Iter>::value_type;
+ using difference_type = typename std::iterator_traits<Iter>::difference_type;
+
+ cmRange(Iter b, Iter e)
+ : Begin(std::move(b))
+ , End(std::move(e))
+ {
+ }
+
+ Iter begin() const { return this->Begin; }
+ Iter end() const { return this->End; }
+ bool empty() const { return this->Begin == this->End; }
+
+ difference_type size() const
+ {
+ return std::distance(this->Begin, this->End);
+ }
+
+ cmRange& advance(difference_type amount) &
+ {
+ std::advance(this->Begin, amount);
+ return *this;
+ }
+
+ cmRange advance(difference_type amount) &&
+ {
+ std::advance(this->Begin, amount);
+ return std::move(*this);
+ }
+
+ cmRange& retreat(difference_type amount) &
+ {
+ std::advance(this->End, -amount);
+ return *this;
+ }
+
+ cmRange retreat(difference_type amount) &&
+ {
+ std::advance(this->End, -amount);
+ return std::move(*this);
+ }
+
+ template <typename UnaryPredicate>
+ bool all_of(UnaryPredicate p) const
+ {
+ return std::all_of(this->Begin, this->End, std::ref(p));
+ }
+
+ template <typename UnaryPredicate>
+ bool any_of(UnaryPredicate p) const
+ {
+ return std::any_of(this->Begin, this->End, std::ref(p));
+ }
+
+ template <typename UnaryPredicate>
+ bool none_of(UnaryPredicate p) const
+ {
+ return std::none_of(this->Begin, this->End, std::ref(p));
+ }
+
+ template <typename UnaryPredicate>
+ auto filter(UnaryPredicate p) const
+ -> cmRange<RangeIterators::FilterIterator<Iter, UnaryPredicate>>
+ {
+ using It = RangeIterators::FilterIterator<Iter, UnaryPredicate>;
+ return { It(this->Begin, this->End, p), It(this->End, this->End, p) };
+ }
+
+ template <typename UnaryFunction>
+ auto transform(UnaryFunction f) const
+ -> cmRange<RangeIterators::TransformIterator<Iter, UnaryFunction>>
+ {
+ using It = RangeIterators::TransformIterator<Iter, UnaryFunction>;
+ return { It(this->Begin, f), It(this->End, f) };
+ }
+
+private:
+ Iter Begin;
+ Iter End;
+};
+
+template <typename Iter1, typename Iter2>
+bool operator==(cmRange<Iter1> const& left, cmRange<Iter2> const& right)
+{
+ return left.size() == right.size() &&
+ std::equal(left.begin(), left.end(), right.begin());
+}
+
+template <typename Iter1, typename Iter2>
+auto cmMakeRange(Iter1 begin, Iter2 end) -> cmRange<Iter1>
+{
+ return { begin, end };
+}
+
+template <typename Range>
+auto cmMakeRange(Range const& range) -> cmRange<decltype(range.begin())>
+{
+ return { range.begin(), range.end() };
+}
+
+template <typename Range>
+auto cmReverseRange(Range const& range) -> cmRange<decltype(range.rbegin())>
+{
+ return { range.rbegin(), range.rend() };
+}
+
+#endif
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index 6bd071cfb1..41555e8e3a 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -5,6 +5,7 @@
#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 2a0ccb410a..0d8f1cc0bf 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -4,11 +4,11 @@
#include <sstream>
-#include "cmAlgorithms.h"
#include "cmGlobalGenerator.h"
#include "cmInstalledFile.h"
#include "cmMakefile.h"
#include "cmProperty.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmSystemTools.h"
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 15c8a613a1..31273ccd90 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -11,6 +11,7 @@
#include "cmAlgorithms.h"
#include "cmProperty.h"
#include "cmPropertyMap.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStatePrivate.h"
#include "cmStateTypes.h"
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 44ba82a2d7..252d9859dd 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -13,6 +13,7 @@
#include "cmCryptoHash.h"
#include "cmGeneratorExpression.h"
#include "cmMakefile.h"
+#include "cmRange.h"
#include "cmStringReplaceHelper.h"
#include "cmSystemTools.h"
#include "cmTimestamp.h"
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 2392473f3c..d762106f09 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -5,6 +5,7 @@
#include "cmAlgorithms.h"
#include "cmDuration.h"
#include "cmProcessOutput.h"
+#include "cmRange.h"
#include "cm_sys_stat.h"
#include "cm_uv.h"
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d1e4f06702..46f930a2d1 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -21,6 +21,7 @@
#include "cmMessageType.h"
#include "cmMessenger.h"
#include "cmProperty.h"
+#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceFileLocationKind.h"
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index a0e309da37..571cd09094 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -5,7 +5,6 @@
#include <ostream>
#include <utility>
-#include "cmAlgorithms.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmListFileCache.h"
@@ -13,6 +12,7 @@
#include "cmOutputConverter.h"
#include "cmProperty.h"
#include "cmPropertyMap.h"
+#include "cmRange.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTest.h"
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index da34bca723..4b0707b8d8 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -5,10 +5,10 @@
#include "cmsys/FStream.hxx"
#include <stdio.h>
-#include "cmAlgorithms.h"
#include "cmDuration.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 1139a4c16a..6e1a27cdbd 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -9,6 +9,7 @@
#include "cmMakefile.h"
#include "cmQtAutoGeneratorMocUic.h"
#include "cmQtAutoGeneratorRcc.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index f6a9153f96..91f7e2500b 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -7,6 +7,7 @@ include_directories(
set(CMakeLib_TESTS
testGeneratedFileStream.cxx
testRST.cxx
+ testRange.cxx
testString.cxx
testSystemTools.cxx
testUTF8.cxx
diff --git a/Tests/CMakeLib/testRange.cxx b/Tests/CMakeLib/testRange.cxx
new file mode 100644
index 0000000000..5ae805ffde
--- /dev/null
+++ b/Tests/CMakeLib/testRange.cxx
@@ -0,0 +1,45 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmRange.h"
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#define ASSERT_TRUE(x) \
+ do { \
+ if (!(x)) { \
+ std::cout << "ASSERT_TRUE(" #x ") failed on line " << __LINE__ << "\n"; \
+ return false; \
+ } \
+ } while (false)
+
+int testRange(int /*unused*/, char* /*unused*/ [])
+{
+ std::vector<int> const testData = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ ASSERT_TRUE(!cmMakeRange(testData).empty());
+ ASSERT_TRUE(cmMakeRange(testData).size() == 10);
+
+ ASSERT_TRUE(!cmMakeRange(testData).advance(5).empty());
+ ASSERT_TRUE(cmMakeRange(testData).advance(5).size() == 5);
+
+ ASSERT_TRUE(cmMakeRange(testData).advance(5).retreat(5).empty());
+ ASSERT_TRUE(cmMakeRange(testData).advance(5).retreat(5).size() == 0);
+
+ ASSERT_TRUE(cmMakeRange(testData).any_of([](int n) { return n % 3 == 0; }));
+ ASSERT_TRUE(cmMakeRange(testData).all_of([](int n) { return n < 11; }));
+ ASSERT_TRUE(cmMakeRange(testData).none_of([](int n) { return n > 11; }));
+
+ std::vector<int> const evenData = { 2, 4, 6, 8, 10 };
+ ASSERT_TRUE(cmMakeRange(testData).filter([](int n) { return n % 2 == 0; }) ==
+ cmMakeRange(evenData));
+
+ std::vector<std::string> const stringRange = { "1", "2", "3", "4", "5" };
+ ASSERT_TRUE(cmMakeRange(testData)
+ .transform([](int n) { return std::to_string(n); })
+ .retreat(5) == cmMakeRange(stringRange));
+
+ return 0;
+}