15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier
95a83710eSEric Fiselier // <utility>
105a83710eSEric Fiselier
115a83710eSEric Fiselier // template<ValueType T, size_t N>
125a83710eSEric Fiselier // requires Swappable<T>
135a83710eSEric Fiselier // void
145a83710eSEric Fiselier // swap(T (&a)[N], T (&b)[N]);
155a83710eSEric Fiselier
16*6adbc83eSChristopher Di Bella #include <algorithm>
175a83710eSEric Fiselier #include <cassert>
185a83710eSEric Fiselier #include <memory>
19*6adbc83eSChristopher Di Bella #include <type_traits>
20*6adbc83eSChristopher Di Bella #include <utility>
21f07dd8d0SEric Fiselier
22f07dd8d0SEric Fiselier #include "test_macros.h"
23f07dd8d0SEric Fiselier
24f07dd8d0SEric Fiselier
25f07dd8d0SEric Fiselier #if TEST_STD_VER >= 11
26f07dd8d0SEric Fiselier struct CopyOnly {
CopyOnlyCopyOnly27f07dd8d0SEric Fiselier CopyOnly() {}
CopyOnlyCopyOnly28f07dd8d0SEric Fiselier CopyOnly(CopyOnly const&) noexcept {}
operator =CopyOnly29f07dd8d0SEric Fiselier CopyOnly& operator=(CopyOnly const&) { return *this; }
30f07dd8d0SEric Fiselier };
31f07dd8d0SEric Fiselier
32f07dd8d0SEric Fiselier
33f07dd8d0SEric Fiselier struct NoexceptMoveOnly {
NoexceptMoveOnlyNoexceptMoveOnly34f07dd8d0SEric Fiselier NoexceptMoveOnly() {}
NoexceptMoveOnlyNoexceptMoveOnly35f07dd8d0SEric Fiselier NoexceptMoveOnly(NoexceptMoveOnly&&) noexcept {}
operator =NoexceptMoveOnly36f07dd8d0SEric Fiselier NoexceptMoveOnly& operator=(NoexceptMoveOnly&&) noexcept { return *this; }
37f07dd8d0SEric Fiselier };
38f07dd8d0SEric Fiselier
39f07dd8d0SEric Fiselier struct NotMoveConstructible {
NotMoveConstructibleNotMoveConstructible40f07dd8d0SEric Fiselier NotMoveConstructible() {}
operator =NotMoveConstructible41f07dd8d0SEric Fiselier NotMoveConstructible& operator=(NotMoveConstructible&&) { return *this; }
42f07dd8d0SEric Fiselier private:
43f07dd8d0SEric Fiselier NotMoveConstructible(NotMoveConstructible&&);
44f07dd8d0SEric Fiselier };
45f07dd8d0SEric Fiselier
46f07dd8d0SEric Fiselier template <class Tp>
47f07dd8d0SEric Fiselier auto can_swap_test(int) -> decltype(std::swap(std::declval<Tp>(), std::declval<Tp>()));
48f07dd8d0SEric Fiselier
49f07dd8d0SEric Fiselier template <class Tp>
50f07dd8d0SEric Fiselier auto can_swap_test(...) -> std::false_type;
51f07dd8d0SEric Fiselier
52f07dd8d0SEric Fiselier template <class Tp>
can_swap()53f07dd8d0SEric Fiselier constexpr bool can_swap() {
54f07dd8d0SEric Fiselier return std::is_same<decltype(can_swap_test<Tp>(0)), void>::value;
55f07dd8d0SEric Fiselier }
565a83710eSEric Fiselier #endif
575a83710eSEric Fiselier
5828e01871SZoe Carver #if TEST_STD_VER > 17
test_swap_constexpr()5928e01871SZoe Carver constexpr bool test_swap_constexpr()
6028e01871SZoe Carver {
6128e01871SZoe Carver int i[3] = {1, 2, 3};
6228e01871SZoe Carver int j[3] = {4, 5, 6};
6328e01871SZoe Carver std::swap(i, j);
6428e01871SZoe Carver return i[0] == 4 &&
6528e01871SZoe Carver i[1] == 5 &&
6628e01871SZoe Carver i[2] == 6 &&
6728e01871SZoe Carver j[0] == 1 &&
6828e01871SZoe Carver j[1] == 2 &&
6928e01871SZoe Carver j[2] == 3;
7028e01871SZoe Carver }
7128e01871SZoe Carver #endif // TEST_STD_VER > 17
72f07dd8d0SEric Fiselier
main(int,char **)732df59c50SJF Bastien int main(int, char**)
74f07dd8d0SEric Fiselier {
755a83710eSEric Fiselier {
765a83710eSEric Fiselier int i[3] = {1, 2, 3};
775a83710eSEric Fiselier int j[3] = {4, 5, 6};
785a83710eSEric Fiselier std::swap(i, j);
795a83710eSEric Fiselier assert(i[0] == 4);
805a83710eSEric Fiselier assert(i[1] == 5);
815a83710eSEric Fiselier assert(i[2] == 6);
825a83710eSEric Fiselier assert(j[0] == 1);
835a83710eSEric Fiselier assert(j[1] == 2);
845a83710eSEric Fiselier assert(j[2] == 3);
855a83710eSEric Fiselier }
86f07dd8d0SEric Fiselier #if TEST_STD_VER >= 11
875a83710eSEric Fiselier {
885a83710eSEric Fiselier std::unique_ptr<int> i[3];
895a83710eSEric Fiselier for (int k = 0; k < 3; ++k)
905a83710eSEric Fiselier i[k].reset(new int(k+1));
915a83710eSEric Fiselier std::unique_ptr<int> j[3];
925a83710eSEric Fiselier for (int k = 0; k < 3; ++k)
935a83710eSEric Fiselier j[k].reset(new int(k+4));
945a83710eSEric Fiselier std::swap(i, j);
955a83710eSEric Fiselier assert(*i[0] == 4);
965a83710eSEric Fiselier assert(*i[1] == 5);
975a83710eSEric Fiselier assert(*i[2] == 6);
985a83710eSEric Fiselier assert(*j[0] == 1);
995a83710eSEric Fiselier assert(*j[1] == 2);
1005a83710eSEric Fiselier assert(*j[2] == 3);
1015a83710eSEric Fiselier }
1025a83710eSEric Fiselier {
103f07dd8d0SEric Fiselier using CA = CopyOnly[42];
104f07dd8d0SEric Fiselier using MA = NoexceptMoveOnly[42];
105f07dd8d0SEric Fiselier using NA = NotMoveConstructible[42];
106f07dd8d0SEric Fiselier static_assert(can_swap<CA&>(), "");
107f07dd8d0SEric Fiselier static_assert(can_swap<MA&>(), "");
108f07dd8d0SEric Fiselier static_assert(!can_swap<NA&>(), "");
109f07dd8d0SEric Fiselier
110f07dd8d0SEric Fiselier CA ca;
111f07dd8d0SEric Fiselier MA ma;
112f07dd8d0SEric Fiselier static_assert(!noexcept(std::swap(ca, ca)), "");
113f07dd8d0SEric Fiselier static_assert(noexcept(std::swap(ma, ma)), "");
114f07dd8d0SEric Fiselier }
1155a83710eSEric Fiselier #endif
1162df59c50SJF Bastien
11728e01871SZoe Carver #if TEST_STD_VER > 17
11828e01871SZoe Carver static_assert(test_swap_constexpr());
11928e01871SZoe Carver #endif // TEST_STD_VER > 17
12028e01871SZoe Carver
1212df59c50SJF Bastien return 0;
1225a83710eSEric Fiselier }
123