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
23struct NonAssignable {
24  NonAssignable& operator=(NonAssignable const&) = delete;
25  NonAssignable& operator=(NonAssignable&&) = delete;
26};
27struct CopyAssignable {
28  CopyAssignable() = default;
29  CopyAssignable& operator=(CopyAssignable const&) = default;
30  CopyAssignable& operator=(CopyAssignable&&) = delete;
31};
32struct MoveAssignable {
33  MoveAssignable() = default;
34  MoveAssignable& operator=(MoveAssignable const&) = delete;
35  MoveAssignable& operator=(MoveAssignable&&) = default;
36};
37
38struct CountAssign {
39  static int copied;
40  static int moved;
41  static void reset() { copied = moved = 0; }
42  CountAssign() = default;
43  CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
44  CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
45};
46int CountAssign::copied = 0;
47int CountAssign::moved = 0;
48
49int main()
50{
51    {
52        typedef std::pair<std::unique_ptr<int>, short> 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