1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// <utility>
11
12// template<ValueType T, size_t N>
13//   requires Swappable<T>
14//   void
15//   swap(T (&a)[N], T (&b)[N]);
16
17#include <utility>
18#include <cassert>
19#include <memory>
20
21#include "test_macros.h"
22
23
24#if TEST_STD_VER >= 11
25struct CopyOnly {
26    CopyOnly() {}
27    CopyOnly(CopyOnly const&) noexcept {}
28    CopyOnly& operator=(CopyOnly const&) { return *this; }
29};
30
31
32struct NoexceptMoveOnly {
33    NoexceptMoveOnly() {}
34    NoexceptMoveOnly(NoexceptMoveOnly&&) noexcept {}
35    NoexceptMoveOnly& operator=(NoexceptMoveOnly&&) noexcept { return *this; }
36};
37
38struct NotMoveConstructible {
39    NotMoveConstructible() {}
40    NotMoveConstructible& operator=(NotMoveConstructible&&) { return *this; }
41private:
42    NotMoveConstructible(NotMoveConstructible&&);
43};
44
45template <class Tp>
46auto can_swap_test(int) -> decltype(std::swap(std::declval<Tp>(), std::declval<Tp>()));
47
48template <class Tp>
49auto can_swap_test(...) -> std::false_type;
50
51template <class Tp>
52constexpr bool can_swap() {
53    return std::is_same<decltype(can_swap_test<Tp>(0)), void>::value;
54}
55#endif
56
57
58int main()
59{
60    {
61        int i[3] = {1, 2, 3};
62        int j[3] = {4, 5, 6};
63        std::swap(i, j);
64        assert(i[0] == 4);
65        assert(i[1] == 5);
66        assert(i[2] == 6);
67        assert(j[0] == 1);
68        assert(j[1] == 2);
69        assert(j[2] == 3);
70    }
71#if TEST_STD_VER >= 11
72    {
73        std::unique_ptr<int> i[3];
74        for (int k = 0; k < 3; ++k)
75            i[k].reset(new int(k+1));
76        std::unique_ptr<int> j[3];
77        for (int k = 0; k < 3; ++k)
78            j[k].reset(new int(k+4));
79        std::swap(i, j);
80        assert(*i[0] == 4);
81        assert(*i[1] == 5);
82        assert(*i[2] == 6);
83        assert(*j[0] == 1);
84        assert(*j[1] == 2);
85        assert(*j[2] == 3);
86    }
87    {
88        using CA = CopyOnly[42];
89        using MA = NoexceptMoveOnly[42];
90        using NA = NotMoveConstructible[42];
91        static_assert(can_swap<CA&>(), "");
92        static_assert(can_swap<MA&>(), "");
93        static_assert(!can_swap<NA&>(), "");
94
95        CA ca;
96        MA ma;
97        static_assert(!noexcept(std::swap(ca, ca)), "");
98        static_assert(noexcept(std::swap(ma, ma)), "");
99    }
100#endif
101}
102