1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 // UNSUPPORTED: c++03, c++11, c++14, c++17
13 // template<input_iterator I, sentinel_for<I> S, weakly_incrementable O>
14 // requires indirectly_copyable<I, O>
15 // constexpr ranges::copy_result<I, O> ranges::copy(I first, S last, O result);
16 // template<input_range R, weakly_incrementable O>
17 // requires indirectly_copyable<iterator_t<R>, O>
18 // constexpr ranges::copy_result<borrowed_iterator_t<R>, O> ranges::copy(R&& r, O result);
27 #include "almost_satisfies_types.h"
28 #include "test_iterators.h"
29 #include "type_algorithms.h"
31 template <class In
, class Out
= In
, class Sent
= sentinel_wrapper
<In
>>
32 concept HasCopyIt
= requires(In in
, Sent sent
, Out out
) { std::ranges::copy(in
, sent
, out
); };
34 static_assert(HasCopyIt
<int*>);
35 static_assert(!HasCopyIt
<InputIteratorNotDerivedFrom
>);
36 static_assert(!HasCopyIt
<InputIteratorNotIndirectlyReadable
>);
37 static_assert(!HasCopyIt
<InputIteratorNotInputOrOutputIterator
>);
38 static_assert(!HasCopyIt
<int*, WeaklyIncrementableNotMovable
>);
39 struct NotIndirectlyCopyable
{};
40 static_assert(!HasCopyIt
<int*, NotIndirectlyCopyable
*>);
41 static_assert(!HasCopyIt
<int*, int*, SentinelForNotSemiregular
>);
42 static_assert(!HasCopyIt
<int*, int*, SentinelForNotWeaklyEqualityComparableWith
>);
44 template <class Range
, class Out
>
45 concept HasCopyR
= requires(Range range
, Out out
) { std::ranges::copy(range
, out
); };
47 static_assert(HasCopyR
<std::array
<int, 10>, int*>);
48 static_assert(!HasCopyR
<InputRangeNotDerivedFrom
, int*>);
49 static_assert(!HasCopyR
<InputRangeNotIndirectlyReadable
, int*>);
50 static_assert(!HasCopyR
<InputRangeNotInputOrOutputIterator
, int*>);
51 static_assert(!HasCopyR
<WeaklyIncrementableNotMovable
, int*>);
52 static_assert(!HasCopyR
<UncheckedRange
<NotIndirectlyCopyable
*>, int*>);
53 static_assert(!HasCopyR
<InputRangeNotSentinelSemiregular
, int*>);
54 static_assert(!HasCopyR
<InputRangeNotSentinelEqualityComparableWith
, int*>);
56 static_assert(std::is_same_v
<std::ranges::copy_result
<int, long>, std::ranges::in_out_result
<int, long>>);
59 template <class In
, class Out
, class Sent
= In
>
60 constexpr void test_iterators() {
63 std::array in
{1, 2, 3, 4};
64 std::array
<int, 4> out
;
65 std::same_as
<std::ranges::in_out_result
<In
, Out
>> auto ret
=
66 std::ranges::copy(In(in
.data()), Sent(In(in
.data() + in
.size())), Out(out
.data()));
68 assert(base(ret
.in
) == in
.data() + in
.size());
69 assert(base(ret
.out
) == out
.data() + out
.size());
72 std::array in
{1, 2, 3, 4};
73 std::array
<int, 4> out
;
74 auto range
= std::ranges::subrange(In(in
.data()), Sent(In(in
.data() + in
.size())));
75 std::same_as
<std::ranges::in_out_result
<In
, Out
>> auto ret
= std::ranges::copy(range
, Out(out
.data()));
77 assert(base(ret
.in
) == in
.data() + in
.size());
78 assert(base(ret
.out
) == out
.data() + out
.size());
82 { // check that an empty range works
84 std::array
<int, 0> in
;
85 std::array
<int, 0> out
;
86 auto ret
= std::ranges::copy(In(in
.data()), Sent(In(in
.data() + in
.size())), Out(out
.data()));
87 assert(base(ret
.in
) == in
.data());
88 assert(base(ret
.out
) == out
.data());
91 std::array
<int, 0> in
;
92 std::array
<int, 0> out
;
93 auto range
= std::ranges::subrange(In(in
.data()), Sent(In(in
.data() + in
.size())));
94 auto ret
= std::ranges::copy(range
, Out(out
.data()));
95 assert(base(ret
.in
) == in
.data());
96 assert(base(ret
.out
) == out
.data());
102 constexpr bool test() {
103 types::for_each(types::forward_iterator_list
<int*>{}, []<class Out
>() {
104 test_iterators
<cpp20_input_iterator
<int*>, Out
, sentinel_wrapper
<cpp20_input_iterator
<int*>>>();
105 test_iterators
<ProxyIterator
<cpp20_input_iterator
<int*>>,
107 sentinel_wrapper
<ProxyIterator
<cpp20_input_iterator
<int*>>>>();
109 types::for_each(types::forward_iterator_list
<int*>{}, []<class In
>() {
110 test_iterators
<In
, Out
>();
111 test_iterators
<In
, Out
, sized_sentinel
<In
>>();
112 test_iterators
<In
, Out
, sentinel_wrapper
<In
>>();
114 test_iterators
<ProxyIterator
<In
>, ProxyIterator
<Out
>>();
115 test_iterators
<ProxyIterator
<In
>, ProxyIterator
<Out
>, sized_sentinel
<ProxyIterator
<In
>>>();
116 test_iterators
<ProxyIterator
<In
>, ProxyIterator
<Out
>, sentinel_wrapper
<ProxyIterator
<In
>>>();
120 { // check that ranges::dangling is returned
121 std::array
<int, 4> out
;
122 std::same_as
<std::ranges::in_out_result
<std::ranges::dangling
, int*>> auto ret
=
123 std::ranges::copy(std::array
{1, 2, 3, 4}, out
.data());
124 assert(ret
.out
== out
.data() + 4);
125 assert((out
== std::array
{1, 2, 3, 4}));
128 { // check that an iterator is returned with a borrowing range
129 std::array in
{1, 2, 3, 4};
130 std::array
<int, 4> out
;
131 std::same_as
<std::ranges::in_out_result
<int*, int*>> auto ret
= std::ranges::copy(std::views::all(in
), out
.data());
132 assert(ret
.in
== in
.data() + 4);
133 assert(ret
.out
== out
.data() + 4);
137 { // check that every element is copied exactly once
140 constexpr CopyOnce() = default;
141 constexpr CopyOnce(const CopyOnce
& other
) = delete;
142 constexpr CopyOnce
& operator=(const CopyOnce
& other
) {
143 assert(!other
.copied
);
149 std::array
<CopyOnce
, 4> in
{};
150 std::array
<CopyOnce
, 4> out
{};
151 auto ret
= std::ranges::copy(in
.begin(), in
.end(), out
.begin());
152 assert(ret
.in
== in
.end());
153 assert(ret
.out
== out
.end());
154 assert(std::all_of(out
.begin(), out
.end(), [](const auto& e
) { return e
.copied
; }));
157 std::array
<CopyOnce
, 4> in
{};
158 std::array
<CopyOnce
, 4> out
{};
159 auto ret
= std::ranges::copy(in
, out
.begin());
160 assert(ret
.in
== in
.end());
161 assert(ret
.out
== out
.end());
162 assert(std::all_of(out
.begin(), out
.end(), [](const auto& e
) { return e
.copied
; }));
166 { // check that the range is copied forwards
167 struct OnlyForwardsCopyable
{
168 OnlyForwardsCopyable
* next
= nullptr;
169 bool canCopy
= false;
170 OnlyForwardsCopyable() = default;
171 constexpr OnlyForwardsCopyable
& operator=(const OnlyForwardsCopyable
&) {
174 next
->canCopy
= true;
179 std::array
<OnlyForwardsCopyable
, 3> in
{};
180 std::array
<OnlyForwardsCopyable
, 3> out
{};
181 out
[0].next
= &out
[1];
182 out
[1].next
= &out
[2];
183 out
[0].canCopy
= true;
184 auto ret
= std::ranges::copy(in
.begin(), in
.end(), out
.begin());
185 assert(ret
.in
== in
.end());
186 assert(ret
.out
== out
.end());
187 assert(out
[0].canCopy
);
188 assert(out
[1].canCopy
);
189 assert(out
[2].canCopy
);
192 std::array
<OnlyForwardsCopyable
, 3> in
{};
193 std::array
<OnlyForwardsCopyable
, 3> out
{};
194 out
[0].next
= &out
[1];
195 out
[1].next
= &out
[2];
196 out
[0].canCopy
= true;
197 auto ret
= std::ranges::copy(in
, out
.begin());
198 assert(ret
.in
== in
.end());
199 assert(ret
.out
== out
.end());
200 assert(out
[0].canCopy
);
201 assert(out
[1].canCopy
);
202 assert(out
[2].canCopy
);
209 int main(int, char**) {
211 static_assert(test());