//===----------------------------------------------------------------------===// // // 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 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME // // template S1, bidirectional_iterator I2> // requires indirectly_movable // constexpr ranges::move_backward_result // ranges::move_backward(I1 first, S1 last, I2 result); // template // requires indirectly_movable, I> // constexpr ranges::move_backward_result, I> // ranges::move_backward(R&& r, I result); #include #include #include #include #include #include #include #include "almost_satisfies_types.h" #include "MoveOnly.h" #include "test_iterators.h" template > concept HasMoveBackwardIt = requires(In in, Sent sent, Out out) { std::ranges::move_backward(in, sent, out); }; static_assert(HasMoveBackwardIt); static_assert(!HasMoveBackwardIt); static_assert(!HasMoveBackwardIt); static_assert(!HasMoveBackwardIt); static_assert(!HasMoveBackwardIt); struct NotIndirectlyCopyable {}; static_assert(!HasMoveBackwardIt); static_assert(!HasMoveBackwardIt); static_assert(!HasMoveBackwardIt); template concept HasMoveBackwardR = requires(Range range, Out out) { std::ranges::move_backward(range, out); }; static_assert(HasMoveBackwardR, int*>); static_assert(!HasMoveBackwardR); static_assert(!HasMoveBackwardR); static_assert(!HasMoveBackwardR); static_assert(!HasMoveBackwardR); static_assert(!HasMoveBackwardR, int*>); static_assert(!HasMoveBackwardR); static_assert(!HasMoveBackwardR); static_assert(!HasMoveBackwardR, WeaklyIncrementableNotMovable>); static_assert(std::is_same_v, std::ranges::in_out_result>); template constexpr void test(std::array in) { { std::array out; std::same_as> decltype(auto) ret = std::ranges::move_backward(In(in.data()), Sent(In(in.data() + in.size())), Out(out.data() + out.size())); assert(in == out); assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } { std::array out; auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data() + in.size()))); std::same_as> decltype(auto) ret = std::ranges::move_backward(range, Out(out.data() + out.size())); assert(in == out); assert(base(ret.in) == in.data() + in.size()); assert(base(ret.out) == out.data()); } } template constexpr void test_iterators() { // simple test test({1, 2, 3, 4}); // check that an empty range works test({}); } template constexpr void test_containers() { { InContainer in {1, 2, 3, 4}; OutContainer out(4); std::same_as> auto ret = std::ranges::move_backward(In(in.begin()), Sent(In(in.end())), Out(out.end())); assert(std::ranges::equal(in, out)); assert(base(ret.in) == in.end()); assert(base(ret.out) == out.begin()); } { InContainer in {1, 2, 3, 4}; OutContainer out(4); auto range = std::ranges::subrange(In(in.begin()), Sent(In(in.end()))); std::same_as> auto ret = std::ranges::move_backward(range, Out(out.end())); assert(std::ranges::equal(in, out)); assert(base(ret.in) == in.end()); assert(base(ret.out) == out.begin()); } } template