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<class T>
13//   requires MoveAssignable<T> && MoveConstructible<T>
14//   void
15//   swap(T& a, T& b);
16
17#include <utility>
18#include <cassert>
19#include <memory>
20
21#include "test_macros.h"
22
23#if TEST_STD_VER >= 11
24struct CopyOnly {
25    CopyOnly() {}
26    CopyOnly(CopyOnly const&) noexcept {}
27    CopyOnly& operator=(CopyOnly const&) { return *this; }
28};
29
30struct MoveOnly {
31    MoveOnly() {}
32    MoveOnly(MoveOnly&&) {}
33    MoveOnly& operator=(MoveOnly&&) noexcept { return *this; }
34};
35
36struct NoexceptMoveOnly {
37    NoexceptMoveOnly() {}
38    NoexceptMoveOnly(NoexceptMoveOnly&&) noexcept {}
39    NoexceptMoveOnly& operator=(NoexceptMoveOnly&&) noexcept { return *this; }
40};
41
42struct NotMoveConstructible {
43    NotMoveConstructible& operator=(NotMoveConstructible&&) { return *this; }
44private:
45    NotMoveConstructible(NotMoveConstructible&&);
46};
47
48struct NotMoveAssignable {
49    NotMoveAssignable(NotMoveAssignable&&);
50private:
51    NotMoveAssignable& operator=(NotMoveAssignable&&);
52};
53
54template <class Tp>
55auto can_swap_test(int) -> decltype(std::swap(std::declval<Tp>(), std::declval<Tp>()));
56
57template <class Tp>
58auto can_swap_test(...) -> std::false_type;
59
60template <class Tp>
61constexpr bool can_swap() {
62    return std::is_same<decltype(can_swap_test<Tp>(0)), void>::value;
63}
64#endif
65
66int main()
67{
68
69    {
70        int i = 1;
71        int j = 2;
72        std::swap(i, j);
73        assert(i == 2);
74        assert(j == 1);
75    }
76#if TEST_STD_VER >= 11
77    {
78
79        std::unique_ptr<int> i(new int(1));
80        std::unique_ptr<int> j(new int(2));
81        std::swap(i, j);
82        assert(*i == 2);
83        assert(*j == 1);
84
85    }
86    {
87        // test that the swap
88        static_assert(can_swap<CopyOnly&>(), "");
89        static_assert(can_swap<MoveOnly&>(), "");
90        static_assert(can_swap<NoexceptMoveOnly&>(), "");
91
92        static_assert(!can_swap<NotMoveConstructible&>(), "");
93        static_assert(!can_swap<NotMoveAssignable&>(), "");
94
95        CopyOnly c;
96        MoveOnly m;
97        NoexceptMoveOnly nm;
98        static_assert(!noexcept(std::swap(c, c)), "");
99        static_assert(!noexcept(std::swap(m, m)), "");
100        static_assert(noexcept(std::swap(nm, nm)), "");
101    }
102#endif
103}
104