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 // UNSUPPORTED: c++98, c++03
11
12 // <utility>
13
14 // template <class T1, class T2> struct pair
15
16 // pair& operator=(pair&& p);
17
18 #include <utility>
19 #include <memory>
20 #include <cassert>
21
22
23 struct NonAssignable {
24 NonAssignable& operator=(NonAssignable const&) = delete;
25 NonAssignable& operator=(NonAssignable&&) = delete;
26 };
27 struct CopyAssignable {
28 CopyAssignable() = default;
29 CopyAssignable& operator=(CopyAssignable const&) = default;
30 CopyAssignable& operator=(CopyAssignable&&) = delete;
31 };
32 struct MoveAssignable {
33 MoveAssignable() = default;
34 MoveAssignable& operator=(MoveAssignable const&) = delete;
35 MoveAssignable& operator=(MoveAssignable&&) = default;
36 };
37
38 struct CountAssign {
39 static int copied;
40 static int moved;
resetCountAssign41 static void reset() { copied = moved = 0; }
42 CountAssign() = default;
operator =CountAssign43 CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
operator =CountAssign44 CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
45 };
46 int CountAssign::copied = 0;
47 int CountAssign::moved = 0;
48
main()49 int main()
50 {
51 {
52 typedef std::pair<std::unique_ptr<int>, int> P;
53 P p1(std::unique_ptr<int>(new int(3)), 4);
54 P p2;
55 p2 = std::move(p1);
56 assert(*p2.first == 3);
57 assert(p2.second == 4);
58 }
59 {
60 using P = std::pair<int&, int&&>;
61 int x = 42;
62 int y = 101;
63 int x2 = -1;
64 int y2 = 300;
65 P p1(x, std::move(y));
66 P p2(x2, std::move(y2));
67 p1 = std::move(p2);
68 assert(p1.first == x2);
69 assert(p1.second == y2);
70 }
71 {
72 using P = std::pair<int, NonAssignable>;
73 static_assert(!std::is_move_assignable<P>::value, "");
74 }
75 {
76 // The move decays to the copy constructor
77 CountAssign::reset();
78 using P = std::pair<CountAssign, CopyAssignable>;
79 static_assert(std::is_move_assignable<P>::value, "");
80 P p;
81 P p2;
82 p = std::move(p2);
83 assert(CountAssign::moved == 0);
84 assert(CountAssign::copied == 1);
85 }
86 {
87 CountAssign::reset();
88 using P = std::pair<CountAssign, MoveAssignable>;
89 static_assert(std::is_move_assignable<P>::value, "");
90 P p;
91 P p2;
92 p = std::move(p2);
93 assert(CountAssign::moved == 1);
94 assert(CountAssign::copied == 0);
95 }
96 }
97