//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // UNSUPPORTED: c++03, c++11, c++14, c++17 // template // requires indirectly_copyable // constexpr ranges::copy_n_result // ranges::copy_n(I first, iter_difference_t n, O result); #include #include #include #include #include "almost_satisfies_types.h" #include "test_iterators.h" template concept HasCopyNIt = requires(In in, Count count, Out out) { std::ranges::copy_n(in, count, out); }; static_assert(HasCopyNIt); static_assert(!HasCopyNIt); static_assert(!HasCopyNIt); static_assert(!HasCopyNIt); static_assert(!HasCopyNIt); struct NotIndirectlyCopyable {}; static_assert(!HasCopyNIt); static_assert(!HasCopyNIt); static_assert(!HasCopyNIt); static_assert(std::is_same_v, std::ranges::in_out_result>); template constexpr void test_iterators() { { // simple test std::array in {1, 2, 3, 4}; std::array out; std::same_as> auto ret = std::ranges::copy_n(In(in.data()), in.size(), Out(out.data())); assert(in == out); assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data() + out.size()); } { // check that an empty range works std::array in; std::array out; auto ret = std::ranges::copy_n(In(in.data()), in.size(), Out(out.data())); assert(base(ret.in) == in.data()); assert(base(ret.out) == out.data()); } } template constexpr void test_in_iterators() { test_iterators, Out, sentinel_wrapper>>(); test_iterators, Out>(); test_iterators, Out>(); test_iterators, Out>(); test_iterators, Out>(); } template constexpr void test_proxy_in_iterators() { test_iterators>, Out, sentinel_wrapper>>>(); test_iterators>, Out>(); test_iterators>, Out>(); test_iterators>, Out>(); test_iterators>, Out>(); } constexpr bool test() { test_in_iterators>(); test_in_iterators>(); test_in_iterators>(); test_in_iterators>(); test_in_iterators>(); test_proxy_in_iterators>>(); test_proxy_in_iterators>>(); test_proxy_in_iterators>>(); test_proxy_in_iterators>>(); test_proxy_in_iterators>>(); { // check that every element is copied exactly once struct CopyOnce { bool copied = false; constexpr CopyOnce() = default; constexpr CopyOnce(const CopyOnce& other) = delete; constexpr CopyOnce& operator=(const CopyOnce& other) { assert(!other.copied); copied = true; return *this; } }; std::array in {}; std::array out {}; auto ret = std::ranges::copy_n(in.begin(), in.size(), out.begin()); assert(ret.in == in.end()); assert(ret.out == out.end()); assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.copied; })); } return true; } int main(int, char**) { test(); static_assert(test()); return 0; }