11d83750fSNikolas Klauser //===----------------------------------------------------------------------===//
21d83750fSNikolas Klauser //
31d83750fSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41d83750fSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
51d83750fSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61d83750fSNikolas Klauser //
71d83750fSNikolas Klauser //===----------------------------------------------------------------------===//
81d83750fSNikolas Klauser
91d83750fSNikolas Klauser // <algorithm>
101d83750fSNikolas Klauser
111d83750fSNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17
121d83750fSNikolas Klauser
131d83750fSNikolas Klauser // template<input_iterator I, sentinel_for<I> S, weakly_incrementable O>
141d83750fSNikolas Klauser // requires indirectly_copyable<I, O>
151d83750fSNikolas Klauser // constexpr ranges::copy_result<I, O> ranges::copy(I first, S last, O result);
161d83750fSNikolas Klauser // template<input_range R, weakly_incrementable O>
171d83750fSNikolas Klauser // requires indirectly_copyable<iterator_t<R>, O>
181d83750fSNikolas Klauser // constexpr ranges::copy_result<borrowed_iterator_t<R>, O> ranges::copy(R&& r, O result);
191d83750fSNikolas Klauser
201d83750fSNikolas Klauser #include <algorithm>
211d83750fSNikolas Klauser #include <array>
221d83750fSNikolas Klauser #include <cassert>
23c9080145SNikolas Klauser #include <deque>
241d83750fSNikolas Klauser #include <ranges>
25c9080145SNikolas Klauser #include <vector>
261d83750fSNikolas Klauser
271d83750fSNikolas Klauser #include "almost_satisfies_types.h"
281d83750fSNikolas Klauser #include "test_iterators.h"
291323461fSNikolas Klauser #include "type_algorithms.h"
301d83750fSNikolas Klauser
311d83750fSNikolas Klauser template <class In, class Out = In, class Sent = sentinel_wrapper<In>>
321d83750fSNikolas Klauser concept HasCopyIt = requires(In in, Sent sent, Out out) { std::ranges::copy(in, sent, out); };
331d83750fSNikolas Klauser
341d83750fSNikolas Klauser static_assert(HasCopyIt<int*>);
351d83750fSNikolas Klauser static_assert(!HasCopyIt<InputIteratorNotDerivedFrom>);
361d83750fSNikolas Klauser static_assert(!HasCopyIt<InputIteratorNotIndirectlyReadable>);
371d83750fSNikolas Klauser static_assert(!HasCopyIt<InputIteratorNotInputOrOutputIterator>);
381d83750fSNikolas Klauser static_assert(!HasCopyIt<int*, WeaklyIncrementableNotMovable>);
391d83750fSNikolas Klauser struct NotIndirectlyCopyable {};
401d83750fSNikolas Klauser static_assert(!HasCopyIt<int*, NotIndirectlyCopyable*>);
411d83750fSNikolas Klauser static_assert(!HasCopyIt<int*, int*, SentinelForNotSemiregular>);
421d83750fSNikolas Klauser static_assert(!HasCopyIt<int*, int*, SentinelForNotWeaklyEqualityComparableWith>);
431d83750fSNikolas Klauser
441d83750fSNikolas Klauser template <class Range, class Out>
451d83750fSNikolas Klauser concept HasCopyR = requires(Range range, Out out) { std::ranges::copy(range, out); };
461d83750fSNikolas Klauser
471d83750fSNikolas Klauser static_assert(HasCopyR<std::array<int, 10>, int*>);
481d83750fSNikolas Klauser static_assert(!HasCopyR<InputRangeNotDerivedFrom, int*>);
491d83750fSNikolas Klauser static_assert(!HasCopyR<InputRangeNotIndirectlyReadable, int*>);
501d83750fSNikolas Klauser static_assert(!HasCopyR<InputRangeNotInputOrOutputIterator, int*>);
511d83750fSNikolas Klauser static_assert(!HasCopyR<WeaklyIncrementableNotMovable, int*>);
521d83750fSNikolas Klauser static_assert(!HasCopyR<UncheckedRange<NotIndirectlyCopyable*>, int*>);
531d83750fSNikolas Klauser static_assert(!HasCopyR<InputRangeNotSentinelSemiregular, int*>);
541d83750fSNikolas Klauser static_assert(!HasCopyR<InputRangeNotSentinelEqualityComparableWith, int*>);
551d83750fSNikolas Klauser
561d83750fSNikolas Klauser static_assert(std::is_same_v<std::ranges::copy_result<int, long>, std::ranges::in_out_result<int, long>>);
571d83750fSNikolas Klauser
58c9080145SNikolas Klauser // clang-format off
591d83750fSNikolas Klauser template <class In, class Out, class Sent = In>
test_iterators()601d83750fSNikolas Klauser constexpr void test_iterators() {
611d83750fSNikolas Klauser { // simple test
621d83750fSNikolas Klauser {
631d83750fSNikolas Klauser std::array in{1, 2, 3, 4};
641d83750fSNikolas Klauser std::array<int, 4> out;
651d83750fSNikolas Klauser std::same_as<std::ranges::in_out_result<In, Out>> auto ret =
661d83750fSNikolas Klauser std::ranges::copy(In(in.data()), Sent(In(in.data() + in.size())), Out(out.data()));
671d83750fSNikolas Klauser assert(in == out);
681d83750fSNikolas Klauser assert(base(ret.in) == in.data() + in.size());
691d83750fSNikolas Klauser assert(base(ret.out) == out.data() + out.size());
701d83750fSNikolas Klauser }
711d83750fSNikolas Klauser {
721d83750fSNikolas Klauser std::array in{1, 2, 3, 4};
731d83750fSNikolas Klauser std::array<int, 4> out;
741d83750fSNikolas Klauser auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data() + in.size())));
751d83750fSNikolas Klauser std::same_as<std::ranges::in_out_result<In, Out>> auto ret = std::ranges::copy(range, Out(out.data()));
761d83750fSNikolas Klauser assert(in == out);
771d83750fSNikolas Klauser assert(base(ret.in) == in.data() + in.size());
781d83750fSNikolas Klauser assert(base(ret.out) == out.data() + out.size());
791d83750fSNikolas Klauser }
801d83750fSNikolas Klauser }
811d83750fSNikolas Klauser
821d83750fSNikolas Klauser { // check that an empty range works
831d83750fSNikolas Klauser {
841d83750fSNikolas Klauser std::array<int, 0> in;
851d83750fSNikolas Klauser std::array<int, 0> out;
861d83750fSNikolas Klauser auto ret = std::ranges::copy(In(in.data()), Sent(In(in.data() + in.size())), Out(out.data()));
871d83750fSNikolas Klauser assert(base(ret.in) == in.data());
881d83750fSNikolas Klauser assert(base(ret.out) == out.data());
891d83750fSNikolas Klauser }
901d83750fSNikolas Klauser {
911d83750fSNikolas Klauser std::array<int, 0> in;
921d83750fSNikolas Klauser std::array<int, 0> out;
931d83750fSNikolas Klauser auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data() + in.size())));
941d83750fSNikolas Klauser auto ret = std::ranges::copy(range, Out(out.data()));
951d83750fSNikolas Klauser assert(base(ret.in) == in.data());
961d83750fSNikolas Klauser assert(base(ret.out) == out.data());
971d83750fSNikolas Klauser }
981d83750fSNikolas Klauser }
991d83750fSNikolas Klauser }
100c9080145SNikolas Klauser // clang-format on
1011d83750fSNikolas Klauser
test()1021323461fSNikolas Klauser constexpr bool test() {
103f56dfb78SArthur O'Dwyer types::for_each(types::forward_iterator_list<int*>{}, []<class Out>() {
1041323461fSNikolas Klauser test_iterators<cpp20_input_iterator<int*>, Out, sentinel_wrapper<cpp20_input_iterator<int*>>>();
1051323461fSNikolas Klauser test_iterators<ProxyIterator<cpp20_input_iterator<int*>>,
1061323461fSNikolas Klauser ProxyIterator<Out>,
1071323461fSNikolas Klauser sentinel_wrapper<ProxyIterator<cpp20_input_iterator<int*>>>>();
1081323461fSNikolas Klauser
109f56dfb78SArthur O'Dwyer types::for_each(types::forward_iterator_list<int*>{}, []<class In>() {
110e01b4fe9SNikolas Klauser test_iterators<In, Out>();
111e01b4fe9SNikolas Klauser test_iterators<In, Out, sized_sentinel<In>>();
112e01b4fe9SNikolas Klauser test_iterators<In, Out, sentinel_wrapper<In>>();
113e01b4fe9SNikolas Klauser
1141323461fSNikolas Klauser test_iterators<ProxyIterator<In>, ProxyIterator<Out>>();
1151323461fSNikolas Klauser test_iterators<ProxyIterator<In>, ProxyIterator<Out>, sized_sentinel<ProxyIterator<In>>>();
1161323461fSNikolas Klauser test_iterators<ProxyIterator<In>, ProxyIterator<Out>, sentinel_wrapper<ProxyIterator<In>>>();
1171323461fSNikolas Klauser });
1181323461fSNikolas Klauser });
119a81cc1fcSHui Xie
1201d83750fSNikolas Klauser { // check that ranges::dangling is returned
1211d83750fSNikolas Klauser std::array<int, 4> out;
1221d83750fSNikolas Klauser std::same_as<std::ranges::in_out_result<std::ranges::dangling, int*>> auto ret =
1231d83750fSNikolas Klauser std::ranges::copy(std::array{1, 2, 3, 4}, out.data());
1241d83750fSNikolas Klauser assert(ret.out == out.data() + 4);
1251d83750fSNikolas Klauser assert((out == std::array{1, 2, 3, 4}));
1261d83750fSNikolas Klauser }
1271d83750fSNikolas Klauser
1281d83750fSNikolas Klauser { // check that an iterator is returned with a borrowing range
1291d83750fSNikolas Klauser std::array in{1, 2, 3, 4};
1301d83750fSNikolas Klauser std::array<int, 4> out;
131*d05bada5SDuo Wang std::same_as<std::ranges::in_out_result<std::array<int, 4>::iterator, int*>> auto ret =
132*d05bada5SDuo Wang std::ranges::copy(std::views::all(in), out.data());
133*d05bada5SDuo Wang assert(ret.in == in.end());
1341d83750fSNikolas Klauser assert(ret.out == out.data() + 4);
1351d83750fSNikolas Klauser assert(in == out);
1361d83750fSNikolas Klauser }
1371d83750fSNikolas Klauser
1381d83750fSNikolas Klauser { // check that every element is copied exactly once
1391d83750fSNikolas Klauser struct CopyOnce {
1401d83750fSNikolas Klauser bool copied = false;
1411d83750fSNikolas Klauser constexpr CopyOnce() = default;
1421d83750fSNikolas Klauser constexpr CopyOnce(const CopyOnce& other) = delete;
1431d83750fSNikolas Klauser constexpr CopyOnce& operator=(const CopyOnce& other) {
1441d83750fSNikolas Klauser assert(!other.copied);
1451d83750fSNikolas Klauser copied = true;
1461d83750fSNikolas Klauser return *this;
1471d83750fSNikolas Klauser }
1481d83750fSNikolas Klauser };
1491d83750fSNikolas Klauser {
1501d83750fSNikolas Klauser std::array<CopyOnce, 4> in{};
1511d83750fSNikolas Klauser std::array<CopyOnce, 4> out{};
1521d83750fSNikolas Klauser auto ret = std::ranges::copy(in.begin(), in.end(), out.begin());
1531d83750fSNikolas Klauser assert(ret.in == in.end());
1541d83750fSNikolas Klauser assert(ret.out == out.end());
1551d83750fSNikolas Klauser assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.copied; }));
1561d83750fSNikolas Klauser }
1571d83750fSNikolas Klauser {
1581d83750fSNikolas Klauser std::array<CopyOnce, 4> in{};
1591d83750fSNikolas Klauser std::array<CopyOnce, 4> out{};
1601d83750fSNikolas Klauser auto ret = std::ranges::copy(in, out.begin());
1611d83750fSNikolas Klauser assert(ret.in == in.end());
1621d83750fSNikolas Klauser assert(ret.out == out.end());
1631d83750fSNikolas Klauser assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.copied; }));
1641d83750fSNikolas Klauser }
1651d83750fSNikolas Klauser }
1661d83750fSNikolas Klauser
1671d83750fSNikolas Klauser { // check that the range is copied forwards
1681d83750fSNikolas Klauser struct OnlyForwardsCopyable {
1691d83750fSNikolas Klauser OnlyForwardsCopyable* next = nullptr;
1701d83750fSNikolas Klauser bool canCopy = false;
1711d83750fSNikolas Klauser OnlyForwardsCopyable() = default;
1721d83750fSNikolas Klauser constexpr OnlyForwardsCopyable& operator=(const OnlyForwardsCopyable&) {
1731d83750fSNikolas Klauser assert(canCopy);
1741d83750fSNikolas Klauser if (next != nullptr)
1751d83750fSNikolas Klauser next->canCopy = true;
1761d83750fSNikolas Klauser return *this;
1771d83750fSNikolas Klauser }
1781d83750fSNikolas Klauser };
1791d83750fSNikolas Klauser {
1801d83750fSNikolas Klauser std::array<OnlyForwardsCopyable, 3> in{};
1811d83750fSNikolas Klauser std::array<OnlyForwardsCopyable, 3> out{};
1821d83750fSNikolas Klauser out[0].next = &out[1];
1831d83750fSNikolas Klauser out[1].next = &out[2];
1841d83750fSNikolas Klauser out[0].canCopy = true;
1851d83750fSNikolas Klauser auto ret = std::ranges::copy(in.begin(), in.end(), out.begin());
1861d83750fSNikolas Klauser assert(ret.in == in.end());
1871d83750fSNikolas Klauser assert(ret.out == out.end());
1881d83750fSNikolas Klauser assert(out[0].canCopy);
1891d83750fSNikolas Klauser assert(out[1].canCopy);
1901d83750fSNikolas Klauser assert(out[2].canCopy);
1911d83750fSNikolas Klauser }
1921d83750fSNikolas Klauser {
1931d83750fSNikolas Klauser std::array<OnlyForwardsCopyable, 3> in{};
1941d83750fSNikolas Klauser std::array<OnlyForwardsCopyable, 3> out{};
1951d83750fSNikolas Klauser out[0].next = &out[1];
1961d83750fSNikolas Klauser out[1].next = &out[2];
1971d83750fSNikolas Klauser out[0].canCopy = true;
1981d83750fSNikolas Klauser auto ret = std::ranges::copy(in, out.begin());
1991d83750fSNikolas Klauser assert(ret.in == in.end());
2001d83750fSNikolas Klauser assert(ret.out == out.end());
2011d83750fSNikolas Klauser assert(out[0].canCopy);
2021d83750fSNikolas Klauser assert(out[1].canCopy);
2031d83750fSNikolas Klauser assert(out[2].canCopy);
2041d83750fSNikolas Klauser }
2051d83750fSNikolas Klauser }
2061d83750fSNikolas Klauser
2071d83750fSNikolas Klauser return true;
2081d83750fSNikolas Klauser }
2091d83750fSNikolas Klauser
main(int,char **)2101d83750fSNikolas Klauser int main(int, char**) {
2111d83750fSNikolas Klauser test();
2121d83750fSNikolas Klauser static_assert(test());
2131d83750fSNikolas Klauser
2141d83750fSNikolas Klauser return 0;
2151d83750fSNikolas Klauser }
216