1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14 10 11 // REQUIRES: with-pstl 12 13 // <algorithm> 14 15 // template<class ExecutionPolicy, class ForwardIterator1, class Size, class ForwardIterator2> 16 // ForwardIterator2 copy_n(ExecutionPolicy&& exec, 17 // ForwardIterator1 first, Size n, 18 // ForwardIterator2 result); 19 20 #include <algorithm> 21 #include <vector> 22 23 #include "test_macros.h" 24 #include "test_execution_policies.h" 25 #include "test_iterators.h" 26 27 EXECUTION_POLICY_SFINAE_TEST(copy_n); 28 29 static_assert(sfinae_test_copy_n<int, int*, int*, bool (*)(int)>); 30 static_assert(!sfinae_test_copy_n<std::execution::parallel_policy, int*, int*, int>); 31 32 template <class Iter1, class Iter2> 33 struct TestInt { 34 template <class Policy> 35 void operator()(Policy&& policy) { 36 // simple test 37 for (const int size : {0, 1, 2, 100, 350}) { 38 std::vector<int> a(size); 39 for (int i = 0; i != size; ++i) 40 a[i] = i + 1; 41 42 std::vector<int> out(std::size(a)); 43 decltype(auto) ret = std::copy_n(policy, Iter1(std::data(a)), std::size(a), Iter2(std::data(out))); 44 static_assert(std::is_same_v<decltype(ret), Iter2>); 45 assert(base(ret) == std::data(out) + std::size(out)); 46 for (int i = 0; i != size; ++i) 47 assert(out[i] == i + 1); 48 } 49 } 50 }; 51 52 struct TestIteratorsInt { 53 template <class Iter2> 54 void operator()() { 55 types::for_each(types::forward_iterator_list<int*>{}, 56 TestIteratorWithPolicies<types::partial_instantiation<TestInt, Iter2>::template apply>{}); 57 } 58 }; 59 60 struct CopiedToTester { 61 bool copied_to = false; 62 CopiedToTester() = default; 63 CopiedToTester(const CopiedToTester&) {} 64 CopiedToTester& operator=(const CopiedToTester&) { 65 assert(!copied_to); 66 copied_to = true; 67 return *this; 68 } 69 ~CopiedToTester() = default; 70 }; 71 72 template <class Iter1, class Iter2> 73 struct TestNonTrivial { 74 template <class Policy> 75 void operator()(Policy&& policy) { 76 // simple test 77 for (const int size : {0, 1, 2, 100, 350}) { 78 std::vector<CopiedToTester> a(size); 79 80 std::vector<CopiedToTester> out(std::size(a)); 81 auto ret = std::copy_n(policy, Iter1(std::data(a)), std::size(a), Iter2(std::data(out))); 82 assert(base(ret) == std::data(out) + std::size(out)); 83 assert(std::all_of(std::begin(out), std::end(out), [](CopiedToTester& t) { return t.copied_to; })); 84 assert(std::none_of(std::begin(a), std::end(a), [](CopiedToTester& t) { return t.copied_to; })); 85 } 86 } 87 }; 88 89 struct TestIteratorsNonTrivial { 90 template <class Iter2> 91 void operator()() { 92 types::for_each(types::forward_iterator_list<CopiedToTester*>{}, 93 TestIteratorWithPolicies<types::partial_instantiation<TestNonTrivial, Iter2>::template apply>{}); 94 } 95 }; 96 97 int main(int, char**) { 98 types::for_each(types::forward_iterator_list<int*>{}, TestIteratorsInt{}); 99 types::for_each(types::forward_iterator_list<CopiedToTester*>{}, TestIteratorsNonTrivial{}); 100 101 return 0; 102 } 103