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, 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);
23 #include "almost_satisfies_types.h"
24 #include "test_iterators.h"
26 template <class In
, class Out
= In
, class Count
= std::size_t>
27 concept HasCopyNIt
= requires(In in
, Count count
, Out out
) { std::ranges::copy_n(in
, count
, out
); };
29 static_assert(HasCopyNIt
<int*>);
30 static_assert(!HasCopyNIt
<InputIteratorNotDerivedFrom
>);
31 static_assert(!HasCopyNIt
<InputIteratorNotIndirectlyReadable
>);
32 static_assert(!HasCopyNIt
<InputIteratorNotInputOrOutputIterator
>);
33 static_assert(!HasCopyNIt
<int*, WeaklyIncrementableNotMovable
>);
34 struct NotIndirectlyCopyable
{};
35 static_assert(!HasCopyNIt
<int*, NotIndirectlyCopyable
*>);
36 static_assert(!HasCopyNIt
<int*, int*, SentinelForNotSemiregular
>);
37 static_assert(!HasCopyNIt
<int*, int*, SentinelForNotWeaklyEqualityComparableWith
>);
39 static_assert(std::is_same_v
<std::ranges::copy_result
<int, long>, std::ranges::in_out_result
<int, long>>);
41 template <class In
, class Out
, class Sent
= In
>
42 constexpr void test_iterators() {
44 std::array in
{1, 2, 3, 4};
45 std::array
<int, 4> out
;
46 std::same_as
<std::ranges::in_out_result
<In
, Out
>> auto ret
=
47 std::ranges::copy_n(In(in
.data()), in
.size(), Out(out
.data()));
49 assert(base(ret
.in
) == in
.data() + in
.size());
50 assert(base(ret
.out
) == out
.data() + out
.size());
53 { // check that an empty range works
54 std::array
<int, 0> in
;
55 std::array
<int, 0> out
;
56 auto ret
= std::ranges::copy_n(In(in
.data()), in
.size(), Out(out
.begin()));
57 assert(base(ret
.in
) == in
.data());
58 assert(base(ret
.out
) == out
.data());
63 constexpr void test_in_iterators() {
64 test_iterators
<cpp20_input_iterator
<int*>, Out
, sentinel_wrapper
<cpp20_input_iterator
<int*>>>();
65 test_iterators
<forward_iterator
<int*>, Out
>();
66 test_iterators
<bidirectional_iterator
<int*>, Out
>();
67 test_iterators
<random_access_iterator
<int*>, Out
>();
68 test_iterators
<contiguous_iterator
<int*>, Out
>();
72 constexpr void test_proxy_in_iterators() {
73 test_iterators
<ProxyIterator
<cpp20_input_iterator
<int*>>, Out
, sentinel_wrapper
<ProxyIterator
<cpp20_input_iterator
<int*>>>>();
74 test_iterators
<ProxyIterator
<forward_iterator
<int*>>, Out
>();
75 test_iterators
<ProxyIterator
<bidirectional_iterator
<int*>>, Out
>();
76 test_iterators
<ProxyIterator
<random_access_iterator
<int*>>, Out
>();
77 test_iterators
<ProxyIterator
<contiguous_iterator
<int*>>, Out
>();
80 constexpr bool test() {
81 test_in_iterators
<cpp20_input_iterator
<int*>>();
82 test_in_iterators
<forward_iterator
<int*>>();
83 test_in_iterators
<bidirectional_iterator
<int*>>();
84 test_in_iterators
<random_access_iterator
<int*>>();
85 test_in_iterators
<contiguous_iterator
<int*>>();
87 test_proxy_in_iterators
<ProxyIterator
<cpp20_input_iterator
<int*>>>();
88 test_proxy_in_iterators
<ProxyIterator
<forward_iterator
<int*>>>();
89 test_proxy_in_iterators
<ProxyIterator
<bidirectional_iterator
<int*>>>();
90 test_proxy_in_iterators
<ProxyIterator
<random_access_iterator
<int*>>>();
91 test_proxy_in_iterators
<ProxyIterator
<contiguous_iterator
<int*>>>();
93 { // check that every element is copied exactly once
96 constexpr CopyOnce() = default;
97 constexpr CopyOnce(const CopyOnce
& other
) = delete;
98 constexpr CopyOnce
& operator=(const CopyOnce
& other
) {
99 assert(!other
.copied
);
104 std::array
<CopyOnce
, 4> in
{};
105 std::array
<CopyOnce
, 4> out
{};
106 auto ret
= std::ranges::copy_n(in
.data(), in
.size(), out
.begin());
107 assert(ret
.in
== in
.end());
108 assert(ret
.out
== out
.end());
109 assert(std::all_of(out
.begin(), out
.end(), [](const auto& e
) { return e
.copied
; }));
115 int main(int, char**) {
117 static_assert(test());