summaryrefslogtreecommitdiffstats
path: root/Utilities
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities')
-rw-r--r--Utilities/CMakeLists.txt2
-rwxr-xr-xUtilities/GitSetup/setup-user8
-rw-r--r--Utilities/IWYU/mapping.imp3
-rwxr-xr-xUtilities/Release/push.bash3
-rw-r--r--Utilities/Sphinx/cmake.py5
-rwxr-xr-xUtilities/Sphinx/create_identifiers.py1
-rw-r--r--Utilities/cmcurl/CMake/cmake_uninstall.cmake.in2
-rw-r--r--Utilities/std/.gitattributes3
-rw-r--r--Utilities/std/cm/bits/erase_if.hxx29
-rw-r--r--Utilities/std/cm/deque40
-rw-r--r--Utilities/std/cm/list39
-rw-r--r--Utilities/std/cm/map44
-rw-r--r--Utilities/std/cm/set43
-rw-r--r--Utilities/std/cm/string42
-rw-r--r--Utilities/std/cm/type_traits53
-rw-r--r--Utilities/std/cm/unordered_map45
-rw-r--r--Utilities/std/cm/unordered_set45
-rw-r--r--Utilities/std/cm/vector40
-rw-r--r--Utilities/std/cmext/algorithm52
-rw-r--r--Utilities/std/cmext/iterator49
-rw-r--r--Utilities/std/cmext/memory32
21 files changed, 572 insertions, 8 deletions
diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt
index 0564540..22a3d5a 100644
--- a/Utilities/CMakeLists.txt
+++ b/Utilities/CMakeLists.txt
@@ -13,7 +13,7 @@ if(CMAKE_DOC_TARBALL)
endif()
add_custom_command(
OUTPUT ${dir}.stamp
- COMMAND cmake -E remove_directory ${dir}
+ COMMAND cmake -E rm -rf ${dir}
COMMAND cmake -E tar xf ${CMAKE_DOC_TARBALL}
COMMAND cmake -E touch ${dir}.stamp
DEPENDS ${CMAKE_DOC_TARBALL}
diff --git a/Utilities/GitSetup/setup-user b/Utilities/GitSetup/setup-user
index 1af439c..0b98879 100755
--- a/Utilities/GitSetup/setup-user
+++ b/Utilities/GitSetup/setup-user
@@ -20,12 +20,12 @@
# Project configuration instructions: NONE
for (( ; ; )); do
- user_name=$(git config user.name || echo '') &&
- user_email=$(git config user.email || echo '') &&
- if test -n "$user_name" -a -n "$user_email"; then
+ ident="$(git var GIT_AUTHOR_IDENT 2>/dev/null | rev | cut -d' ' -f3- | rev)"
+
+ if test -n "$ident"; then
echo 'Your commits will record as Author:
- '"$user_name <$user_email>"'
+ '"$ident"'
' &&
read -ep 'Is the author name and email address above correct? [Y/n] ' correct &&
if test "$correct" != "n" -a "$correct" != "N"; then
diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp
index ef31e8b..3497b53 100644
--- a/Utilities/IWYU/mapping.imp
+++ b/Utilities/IWYU/mapping.imp
@@ -24,6 +24,7 @@
{ include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] },
{ include: [ "<bits/std_function.h>", private, "<functional>", public ] },
{ include: [ "<bits/refwrap.h>", private, "<functional>", public ] },
+ { include: [ "<bits/std_abs.h>", private, "<stdlib.h>", public ] },
{ include: [ "<bits/stdint-intn.h>", private, "<stdint.h>", public ] },
{ include: [ "<bits/stdint-uintn.h>", private, "<stdint.h>", public ] },
{ include: [ "<bits/time.h>", private, "<time.h>", public ] },
@@ -46,6 +47,8 @@
# HACK: iwyu suggests <ext/alloc_traits.h> and <memory> each time vector[] is used.
# https://github.com/include-what-you-use/include-what-you-use/issues/166
{ include: [ "<ext/alloc_traits.h>", private, "<vector>", public ] },
+ { symbol: [ "std::allocator_traits<std::allocator<cmFileLock> >::value_type", private, "<vector>", public ] },
+ { symbol: [ "std::allocator_traits<std::allocator<cmFileLockPool::ScopePool> >::value_type", private, "<vector>", public ] },
{ symbol: [ "std::allocator_traits<std::allocator<cmComputeComponentGraph::TarjanEntry> >::value_type", private, "<vector>", public ] },
{ symbol: [ "std::allocator_traits<std::allocator<cmFortranFile> >::value_type", private, "<vector>", public ] },
{ symbol: [ "std::allocator_traits<std::allocator<cmGraphEdgeList> >::value_type", private, "<vector>", public ] },
diff --git a/Utilities/Release/push.bash b/Utilities/Release/push.bash
index 1c8efe9..a1c6651 100755
--- a/Utilities/Release/push.bash
+++ b/Utilities/Release/push.bash
@@ -50,6 +50,9 @@ if test -z "$dir"; then
dir="v${version}"
fi
readonly dir
+if ! test -d "${dest}/${dir}"; then
+ mkdir "${dest}/${dir}"
+fi
for f in cmake-${version}*; do
if ! test -f "${f}"; then
diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py
index d903dbe..f164fd0 100644
--- a/Utilities/Sphinx/cmake.py
+++ b/Utilities/Sphinx/cmake.py
@@ -191,6 +191,7 @@ _cmake_index_objs = {
'cpack_gen': _cmake_index_entry('cpack generator'),
'envvar': _cmake_index_entry('envvar'),
'generator': _cmake_index_entry('generator'),
+ 'guide': _cmake_index_entry('guide'),
'manual': _cmake_index_entry('manual'),
'module': _cmake_index_entry('module'),
'policy': _cmake_index_entry('policy'),
@@ -251,7 +252,7 @@ class CMakeTransform(Transform):
env = self.document.settings.env
# Treat some documents as cmake domain objects.
- objtype, sep, tail = env.docname.rpartition('/')
+ objtype, sep, tail = env.docname.partition('/')
make_index_entry = _cmake_index_objs.get(objtype)
if make_index_entry:
title = self.parse_title(env.docname)
@@ -373,6 +374,7 @@ class CMakeDomain(Domain):
'cpack_gen': ObjType('cpack_gen', 'cpack_gen'),
'envvar': ObjType('envvar', 'envvar'),
'generator': ObjType('generator', 'generator'),
+ 'guide': ObjType('guide', 'guide'),
'variable': ObjType('variable', 'variable'),
'module': ObjType('module', 'module'),
'policy': ObjType('policy', 'policy'),
@@ -407,6 +409,7 @@ class CMakeDomain(Domain):
'cpack_gen': CMakeXRefRole(),
'envvar': CMakeXRefRole(),
'generator': CMakeXRefRole(),
+ 'guide': CMakeXRefRole(),
'variable': CMakeXRefRole(),
'module': CMakeXRefRole(),
'policy': CMakeXRefRole(),
diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py
index 6716b48..b5cd914 100755
--- a/Utilities/Sphinx/create_identifiers.py
+++ b/Utilities/Sphinx/create_identifiers.py
@@ -25,6 +25,7 @@ for line in lines:
("envvar", "envvar"),
("variable", "variable"),
("generator", "generator"),
+ ("guide", "guide"),
("target property", "prop_tgt"),
("test property", "prop_test"),
("source file property", "prop_sf"),
diff --git a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
index db8e536..5178fd8 100644
--- a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
+++ b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
@@ -13,7 +13,7 @@ foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
- "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ "@CMAKE_COMMAND@" ARGS "-E rm -f \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
diff --git a/Utilities/std/.gitattributes b/Utilities/std/.gitattributes
index cd20549..ad5459d 100644
--- a/Utilities/std/.gitattributes
+++ b/Utilities/std/.gitattributes
@@ -1 +1,2 @@
-cm/* our-c-style
+cm/** our-c-style
+cmext/** our-c-style
diff --git a/Utilities/std/cm/bits/erase_if.hxx b/Utilities/std/cm/bits/erase_if.hxx
new file mode 100644
index 0000000..8952fb5
--- /dev/null
+++ b/Utilities/std/cm/bits/erase_if.hxx
@@ -0,0 +1,29 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#ifndef cm_bits_erase_if_hxx
+#define cm_bits_erase_if_hxx
+
+namespace cm {
+namespace internals {
+
+template <typename Container, typename Predicate>
+void erase_if(Container& cont, Predicate pred)
+{
+ for (typename Container::iterator iter = cont.begin(), last = cont.end();
+ iter != last;) {
+ if (pred(*iter)) {
+ iter = cont.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+} // namespace internals
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/deque b/Utilities/std/cm/deque
new file mode 100644
index 0000000..4bb6725
--- /dev/null
+++ b/Utilities/std/cm/deque
@@ -0,0 +1,40 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_deque
+#define cm_deque
+
+#include <algorithm>
+#include <deque> // IWYU pragma: export
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase;
+using std::erase_if;
+
+#else
+
+template <typename T, typename Allocator, typename V>
+inline void erase(std::deque<T, Allocator>& cont, const V& value)
+{
+ cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end());
+}
+
+template <typename T, typename Allocator, typename Predicate>
+inline void erase_if(std::deque<T, Allocator>& cont, Predicate pred)
+{
+ cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end());
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/list b/Utilities/std/cm/list
new file mode 100644
index 0000000..ba5d94a
--- /dev/null
+++ b/Utilities/std/cm/list
@@ -0,0 +1,39 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_list
+#define cm_list
+
+#include <list> // IWYU pragma: export
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase;
+using std::erase_if;
+
+#else
+
+template <typename T, typename Allocator, typename V>
+inline void erase(std::list<T, Allocator>& cont, const V& value)
+{
+ cont.remove_if([&](auto& elem) { return elem == value; });
+}
+
+template <typename T, typename Allocator, typename Predicate>
+inline void erase_if(std::list<T, Allocator>& cont, Predicate pred)
+{
+ cont.remove_if(pred);
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/map b/Utilities/std/cm/map
new file mode 100644
index 0000000..e348dec
--- /dev/null
+++ b/Utilities/std/cm/map
@@ -0,0 +1,44 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_map
+#define cm_map
+
+#include <map> // IWYU pragma: export
+
+#include <cm/bits/erase_if.hxx>
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase_if;
+
+#else
+
+template <typename Key, typename T, typename Compare, typename Allocator,
+ typename Predicate>
+inline void erase_if(std::map<Key, T, Compare, Allocator>& cont,
+ Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+template <typename Key, typename T, typename Compare, typename Allocator,
+ typename Predicate>
+inline void erase_if(std::multimap<Key, T, Compare, Allocator>& cont,
+ Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/set b/Utilities/std/cm/set
new file mode 100644
index 0000000..56dd474
--- /dev/null
+++ b/Utilities/std/cm/set
@@ -0,0 +1,43 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_set
+#define cm_set
+
+#include <set> // IWYU pragma: export
+
+#include <cm/bits/erase_if.hxx>
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase_if;
+
+#else
+
+template <typename Key, typename Compare, typename Allocator,
+ typename Predicate>
+inline void erase_if(std::set<Key, Compare, Allocator>& cont, Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+template <typename Key, typename Compare, typename Allocator,
+ typename Predicate>
+inline void erase_if(std::multiset<Key, Compare, Allocator>& cont,
+ Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/string b/Utilities/std/cm/string
new file mode 100644
index 0000000..cc4c796
--- /dev/null
+++ b/Utilities/std/cm/string
@@ -0,0 +1,42 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_string
+#define cm_string
+
+#include <algorithm>
+#include <string> // IWYU pragma: export
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase;
+using std::erase_if;
+
+#else
+
+template <typename T, typename Traits, typename Allocator, typename V>
+inline void erase(std::basic_string<T, Traits, Allocator>& cont,
+ const V& value)
+{
+ cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end());
+}
+
+template <typename T, typename Traits, typename Allocator, typename Predicate>
+inline void erase_if(std::basic_string<T, Traits, Allocator>& cont,
+ Predicate pred)
+{
+ cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end());
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/type_traits b/Utilities/std/cm/type_traits
new file mode 100644
index 0000000..4dfe17b
--- /dev/null
+++ b/Utilities/std/cm/type_traits
@@ -0,0 +1,53 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_type_traits
+#define cm_type_traits
+
+#include <type_traits> // IWYU pragma: export
+
+namespace cm {
+
+#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
+
+// Miscellaneous transformations
+template <bool B, typename T = void>
+using enable_if_t = std::enable_if_t<B, T>;
+
+#else
+
+// Miscellaneous transformations
+template <bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+#endif
+
+#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703)
+
+// Helper classes
+using std::bool_constant;
+
+// Miscellaneous transformations
+using std::invoke_result;
+using std::invoke_result_t;
+
+#else
+
+// Helper classes
+template <bool B>
+using bool_constant = std::integral_constant<bool, B>;
+
+// Miscellaneous transformations
+template <typename F, typename... ArgTypes>
+using invoke_result = std::result_of<F(ArgTypes...)>;
+
+template <class F, typename... ArgTypes>
+using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/unordered_map b/Utilities/std/cm/unordered_map
new file mode 100644
index 0000000..5b8a456
--- /dev/null
+++ b/Utilities/std/cm/unordered_map
@@ -0,0 +1,45 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_unordered_map
+#define cm_unordered_map
+
+#include <unordered_map> // IWYU pragma: export
+
+#include <cm/bits/erase_if.hxx>
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase_if;
+
+#else
+
+template <typename Key, typename T, typename Hash, typename KeyEqual,
+ typename Allocator, typename Predicate>
+inline void erase_if(
+ std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& cont, Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+template <typename Key, typename T, typename Hash, typename KeyEqual,
+ typename Allocator, typename Predicate>
+inline void erase_if(
+ std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& cont,
+ Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/unordered_set b/Utilities/std/cm/unordered_set
new file mode 100644
index 0000000..9debac4
--- /dev/null
+++ b/Utilities/std/cm/unordered_set
@@ -0,0 +1,45 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_unordered_set
+#define cm_unordered_set
+
+#include <unordered_set> // IWYU pragma: export
+
+#include <cm/bits/erase_if.hxx>
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase_if;
+
+#else
+
+template <typename Key, typename Hash, typename KeyEqual, typename Allocator,
+ typename Predicate>
+inline void erase_if(std::unordered_set<Key, Hash, KeyEqual, Allocator>& cont,
+ Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+template <typename Key, typename Hash, typename KeyEqual, typename Allocator,
+ typename Predicate>
+inline void erase_if(
+ std::unordered_multiset<Key, Hash, KeyEqual, Allocator>& cont,
+ Predicate pred)
+{
+ internals::erase_if(cont, pred);
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cm/vector b/Utilities/std/cm/vector
new file mode 100644
index 0000000..2dbe704
--- /dev/null
+++ b/Utilities/std/cm/vector
@@ -0,0 +1,40 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cm_vector
+#define cm_vector
+
+#include <algorithm>
+#include <vector> // IWYU pragma: export
+
+namespace cm {
+
+// should be updated when C++20 is finalized
+#if (__cplusplus > 201703L || \
+ (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \
+ defined(__cpp_lib_erase_if)
+
+using std::erase;
+using std::erase_if;
+
+#else
+
+template <typename T, typename Allocator, typename V>
+inline void erase(std::vector<T, Allocator>& cont, const V& value)
+{
+ cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end());
+}
+
+template <typename T, typename Allocator, typename Predicate>
+inline void erase_if(std::vector<T, Allocator>& cont, Predicate pred)
+{
+ cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end());
+}
+
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cmext/algorithm b/Utilities/std/cmext/algorithm
new file mode 100644
index 0000000..609860c
--- /dev/null
+++ b/Utilities/std/cmext/algorithm
@@ -0,0 +1,52 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmext_algorithm
+#define cmext_algorithm
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include <cm/type_traits>
+#include <cmext/iterator>
+
+namespace cm {
+
+template <typename T>
+void append(std::vector<std::unique_ptr<T>>& v,
+ std::vector<std::unique_ptr<T>>&& r)
+{
+ std::transform(r.begin(), r.end(), std::back_inserter(v),
+ [](std::unique_ptr<T>& item) { return std::move(item); });
+ r.clear();
+}
+
+template <typename T>
+void append(std::vector<T*>& v, std::vector<std::unique_ptr<T>> const& r)
+{
+ std::transform(r.begin(), r.end(), std::back_inserter(v),
+ [](const std::unique_ptr<T>& item) { return item.get(); });
+}
+
+template <typename T, typename InputIt,
+ cm::enable_if_t<cm::is_input_iterator<InputIt>::value, int> = 0>
+void append(std::vector<T>& v, InputIt first, InputIt last)
+{
+ v.insert(v.end(), first, last);
+}
+
+template <typename T, typename Range,
+ cm::enable_if_t<cm::is_input_range<Range>::value, int> = 0>
+void append(std::vector<T>& v, Range const& r)
+{
+ v.insert(v.end(), r.begin(), r.end());
+}
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cmext/iterator b/Utilities/std/cmext/iterator
new file mode 100644
index 0000000..ffe94b1
--- /dev/null
+++ b/Utilities/std/cmext/iterator
@@ -0,0 +1,49 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmext_iterator
+#define cmext_iterator
+
+#include <iterator>
+
+#include <cm/type_traits>
+
+namespace cm {
+
+// checks if a type is an iterator type
+template <typename I>
+using is_iterator =
+ std::is_integral<typename std::iterator_traits<I>::difference_type>;
+
+// checks if a type is an input iterator type
+template <typename I>
+using is_input_iterator =
+ std::is_base_of<std::input_iterator_tag,
+ typename std::iterator_traits<I>::iterator_category>;
+
+// checks if a type is a range type: must have a difference_type type
+template <typename Range>
+using is_range = cm::bool_constant<
+ cm::is_iterator<decltype(std::declval<const Range>().begin())>::value &&
+ cm::is_iterator<decltype(std::declval<const Range>().end())>::value>;
+
+// checks if a type is an input range type: must have methods begin() and end()
+// returning an input iterator
+template <typename Range>
+using is_input_range =
+#if defined(_MSC_VER) && _MSC_VER < 1920
+ // MS C++ is not able to evaluate complex type introspection,
+ // so use a simplified version
+ cm::is_input_iterator<typename Range::const_iterator>;
+#else
+ cm::bool_constant<
+ cm::is_input_iterator<decltype(
+ std::declval<const Range>().begin())>::value &&
+ cm::is_input_iterator<decltype(std::declval<const Range>().end())>::value>;
+#endif
+
+} // namespace cm
+
+#endif
diff --git a/Utilities/std/cmext/memory b/Utilities/std/cmext/memory
new file mode 100644
index 0000000..540a3de
--- /dev/null
+++ b/Utilities/std/cmext/memory
@@ -0,0 +1,32 @@
+// -*-c++-*-
+// vim: set ft=cpp:
+
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmext_memory
+#define cmext_memory
+
+#include <cm/type_traits>
+
+namespace cm {
+
+template <typename T, typename O,
+ cm::enable_if_t<
+ std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
+ int> = 0>
+T& static_reference_cast(O& item)
+{
+ return *(static_cast<T*>(item.get()));
+}
+template <typename T, typename O,
+ cm::enable_if_t<
+ std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
+ int> = 0>
+T& dynamic_reference_cast(O& item)
+{
+ return *(dynamic_cast<T*>(item.get()));
+}
+
+} // namespace cm
+
+#endif