mirror of
https://github.com/Kitware/CMake.git
synced 2025-05-09 06:42:18 +08:00
Refactoring: introduce header cmext/algorithm with append functions
This commit is contained in:
parent
d082d0e109
commit
a38d04c076
@ -26,6 +26,7 @@ set(CMakeLib_TESTS
|
||||
testUVRAII.cxx
|
||||
testUVStreambuf.cxx
|
||||
testCMExtMemory.cxx
|
||||
testCMExtAlgorithm.cxx
|
||||
)
|
||||
|
||||
add_executable(testUVProcessChainHelper testUVProcessChainHelper.cxx)
|
||||
|
117
Tests/CMakeLib/testCMExtAlgorithm.cxx
Normal file
117
Tests/CMakeLib/testCMExtAlgorithm.cxx
Normal file
@ -0,0 +1,117 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <cmext/algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
int failed = 0;
|
||||
|
||||
void testAppend()
|
||||
{
|
||||
std::cout << "testAppend()" << std::endl;
|
||||
|
||||
// ----------------------------------------------------
|
||||
// cm::append(Vector, Iterator, Iterator)
|
||||
{
|
||||
std::vector<int> v1{ 1, 2, 3 };
|
||||
std::vector<int> v1_ref{ 1, 2, 3, 4, 5, 6 };
|
||||
std::vector<int> v2{ 4, 5, 6 };
|
||||
std::vector<int> v2_ref{ 4, 5, 6 };
|
||||
|
||||
cm::append(v1, v2.begin(), v2.end());
|
||||
|
||||
if (v1 != v1_ref || v2 != v2_ref) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// cm::append(Vector, Range)
|
||||
{
|
||||
std::vector<int> v1{ 1, 2, 3 };
|
||||
std::vector<int> v1_ref{ 1, 2, 3, 4, 5, 6 };
|
||||
std::vector<int> v2{ 4, 5, 6 };
|
||||
std::vector<int> v2_ref{ 4, 5, 6 };
|
||||
|
||||
cm::append(v1, v2);
|
||||
|
||||
if (v1 != v1_ref || v2 != v2_ref) {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// cm::append(Vector<*>, Vector<unique_ptr>)
|
||||
{
|
||||
std::vector<int*> v1{ new int(1), new int(2), new int(3) };
|
||||
std::vector<int*> v1_ref = v1;
|
||||
std::vector<std::unique_ptr<int>> v2;
|
||||
|
||||
v2.emplace_back(new int(4));
|
||||
v2.emplace_back(new int(5));
|
||||
v2.emplace_back(new int(6));
|
||||
|
||||
cm::append(v1, v2);
|
||||
|
||||
if (v1.size() == 6 && v2.size() == 3) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (v1[i] != v1_ref[i]) {
|
||||
++failed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (v1[i + 3] != v2[i].get()) {
|
||||
++failed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
++failed;
|
||||
}
|
||||
|
||||
// free memory to please memory sanitizer
|
||||
delete v1[0];
|
||||
delete v1[1];
|
||||
delete v1[2];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// cm::append(Vector<unique_ptr>, Vector<unique_ptr>)
|
||||
{
|
||||
std::vector<std::unique_ptr<int>> v1;
|
||||
std::vector<std::unique_ptr<int>> v2;
|
||||
|
||||
v1.emplace_back(new int(1));
|
||||
v1.emplace_back(new int(2));
|
||||
v1.emplace_back(new int(3));
|
||||
|
||||
v2.emplace_back(new int(4));
|
||||
v2.emplace_back(new int(5));
|
||||
v2.emplace_back(new int(6));
|
||||
|
||||
cm::append(v1, std::move(v2));
|
||||
|
||||
if (v1.size() == 6 && v2.empty()) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (*v1[i] != i + 1) {
|
||||
++failed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int testCMExtAlgorithm(int /*unused*/, char* /*unused*/ [])
|
||||
{
|
||||
testAppend();
|
||||
|
||||
return failed;
|
||||
}
|
@ -26,12 +26,19 @@ using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
#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...)>;
|
||||
|
52
Utilities/std/cmext/algorithm
Normal file
52
Utilities/std/cmext/algorithm
Normal file
@ -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
|
49
Utilities/std/cmext/iterator
Normal file
49
Utilities/std/cmext/iterator
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user