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// <algorithm>
10
11// UNSUPPORTED: c++03, c++11, c++14, c++17
12
13// template<input_iterator I, weakly_incrementable O>
14// requires indirectly_copyable<I, O>
15// constexpr ranges::copy_n_result<I, O>
16// ranges::copy_n(I first, iter_difference_t<I> n, O result);
17
18#include <algorithm>
19#include <array>
20#include <cassert>
21#include <ranges>
22#include <vector>
23
24#include "almost_satisfies_types.h"
25#include "test_macros.h"
26#include "test_iterators.h"
27
28template <class In, class Out = In, class Count = std::size_t>
29concept HasCopyNIt = requires(In in, Count count, Out out) { std::ranges::copy_n(in, count, out); };
30
31static_assert(HasCopyNIt<int*>);
32static_assert(!HasCopyNIt<InputIteratorNotDerivedFrom>);
33static_assert(!HasCopyNIt<InputIteratorNotIndirectlyReadable>);
34static_assert(!HasCopyNIt<InputIteratorNotInputOrOutputIterator>);
35static_assert(!HasCopyNIt<int*, WeaklyIncrementableNotMovable>);
36struct NotIndirectlyCopyable {};
37static_assert(!HasCopyNIt<int*, NotIndirectlyCopyable*>);
38static_assert(!HasCopyNIt<int*, int*, SentinelForNotSemiregular>);
39static_assert(!HasCopyNIt<int*, int*, SentinelForNotWeaklyEqualityComparableWith>);
40
41static_assert(std::is_same_v<std::ranges::copy_result<int, long>, std::ranges::in_out_result<int, long>>);
42
43template <class In, class Out>
44constexpr void test_iterators() {
45 { // simple test
46 std::array in{1, 2, 3, 4};
47 std::array<int, 4> out;
48 std::same_as<std::ranges::in_out_result<In, Out>> auto ret =
49 std::ranges::copy_n(In(in.data()), in.size(), Out(out.data()));
50 assert(in == out);
51 assert(base(ret.in) == in.data() + in.size());
52 assert(base(ret.out) == out.data() + out.size());
53 }
54
55 { // check that an empty range works
56 std::array<int, 0> in;
57 std::array<int, 0> out;
58 auto ret = std::ranges::copy_n(In(in.data()), in.size(), Out(out.data()));
59 assert(base(ret.in) == in.data());
60 assert(base(ret.out) == out.data());
61 }
62}
63
64#if TEST_STD_VER >= 23
65constexpr bool test_vector_bool(std::size_t N) {
66 std::vector<bool> in(N, false);
67 for (std::size_t i = 0; i < N; i += 2)
68 in[i] = true;
69
70 { // Test copy with aligned bytes
71 std::vector<bool> out(N);
72 std::ranges::copy_n(in.begin(), N, out.begin());
73 assert(in == out);
74 }
75 { // Test copy with unaligned bytes
76 std::vector<bool> out(N + 8);
77 std::ranges::copy_n(in.begin(), N, out.begin() + 4);
78 for (std::size_t i = 0; i < N; ++i)
79 assert(out[i + 4] == in[i]);
80 }
81
82 return true;
83};
84#endif
85
86constexpr bool test() {
87 types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Out>() {
88 types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class In>() {
89 test_iterators<In, Out>();
90 test_iterators<ProxyIterator<In>, ProxyIterator<Out>>();
91 });
92 });
93
94 { // check that every element is copied exactly once
95 struct CopyOnce {
96 bool copied = false;
97 constexpr CopyOnce() = default;
98 constexpr CopyOnce(const CopyOnce& other) = delete;
99 constexpr CopyOnce& operator=(const CopyOnce& other) {
100 assert(!other.copied);
101 copied = true;
102 return *this;
103 }
104 };
105 std::array<CopyOnce, 4> in{};
106 std::array<CopyOnce, 4> out{};
107 auto ret = std::ranges::copy_n(in.begin(), in.size(), out.begin());
108 assert(ret.in == in.end());
109 assert(ret.out == out.end());
110 assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.copied; }));
111 }
112
113#if TEST_STD_VER >= 23
114 { // Test vector<bool>::iterator optimization
115 assert(test_vector_bool(8));
116 assert(test_vector_bool(19));
117 assert(test_vector_bool(32));
118 assert(test_vector_bool(49));
119 assert(test_vector_bool(64));
120 assert(test_vector_bool(199));
121 assert(test_vector_bool(256));
122 }
123#endif
124
125 return true;
126}
127
128int main(int, char**) {
129 test();
130 static_assert(test());
131
132 return 0;
133}
134

source code of libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_n.pass.cpp