1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: c++98, c++03, c++11, c++14
10 
11 // <map>
12 
13 // class map
14 
15 // template <class... Args>
16 //  pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);          // C++17
17 // template <class... Args>
18 //  pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);               // C++17
19 // template <class... Args>
20 //  iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args); // C++17
21 // template <class... Args>
22 //  iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);      // C++17
23 
24 #include <map>
25 #include <cassert>
26 #include <tuple>
27 
28 class Moveable
29 {
30     Moveable(const Moveable&);
31     Moveable& operator=(const Moveable&);
32 
33     int int_;
34     double double_;
35 public:
36     Moveable() : int_(0), double_(0) {}
37     Moveable(int i, double d) : int_(i), double_(d) {}
38     Moveable(Moveable&& x)
39         : int_(x.int_), double_(x.double_)
40             {x.int_ = -1; x.double_ = -1;}
41     Moveable& operator=(Moveable&& x)
42         {int_ = x.int_; x.int_ = -1;
43          double_ = x.double_; x.double_ = -1;
44          return *this;
45         }
46 
47     bool operator==(const Moveable& x) const
48         {return int_ == x.int_ && double_ == x.double_;}
49     bool operator<(const Moveable& x) const
50         {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);}
51 
52     int get() const {return int_;}
53     bool moved() const {return int_ == -1;}
54 };
55 
56 
57 int main(int, char**)
58 {
59     { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
60         typedef std::map<int, Moveable> M;
61         typedef std::pair<M::iterator, bool> R;
62         M m;
63         R r;
64         for (int i = 0; i < 20; i += 2)
65             m.emplace (i, Moveable(i, (double) i));
66         assert(m.size() == 10);
67 
68         Moveable mv1(3, 3.0);
69         for (int i=0; i < 20; i += 2)
70         {
71             r = m.try_emplace(i, std::move(mv1));
72             assert(m.size() == 10);
73             assert(!r.second);              // was not inserted
74             assert(!mv1.moved());           // was not moved from
75             assert(r.first->first == i);    // key
76         }
77 
78         r = m.try_emplace(-1, std::move(mv1));
79         assert(m.size() == 11);
80         assert(r.second);                   // was inserted
81         assert(mv1.moved());                // was moved from
82         assert(r.first->first == -1);       // key
83         assert(r.first->second.get() == 3); // value
84 
85         Moveable mv2(5, 3.0);
86         r = m.try_emplace(5, std::move(mv2));
87         assert(m.size() == 12);
88         assert(r.second);                   // was inserted
89         assert(mv2.moved());                // was moved from
90         assert(r.first->first == 5);        // key
91         assert(r.first->second.get() == 5); // value
92 
93         Moveable mv3(-1, 3.0);
94         r = m.try_emplace(117, std::move(mv2));
95         assert(m.size() == 13);
96         assert(r.second);                    // was inserted
97         assert(mv2.moved());                 // was moved from
98         assert(r.first->first == 117);       // key
99         assert(r.first->second.get() == -1); // value
100     }
101 
102     {  // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
103         typedef std::map<Moveable, Moveable> M;
104         typedef std::pair<M::iterator, bool> R;
105         M m;
106         R r;
107         for ( int i = 0; i < 20; i += 2 )
108             m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
109         assert(m.size() == 10);
110 
111         Moveable mvkey1(2, 2.0);
112         Moveable mv1(4, 4.0);
113         r = m.try_emplace(std::move(mvkey1), std::move(mv1));
114         assert(m.size() == 10);
115         assert(!r.second);                 // was not inserted
116         assert(!mv1.moved());              // was not moved from
117         assert(!mvkey1.moved());           // was not moved from
118         assert(r.first->first == mvkey1);  // key
119 
120         Moveable mvkey2(3, 3.0);
121         r = m.try_emplace(std::move(mvkey2), std::move(mv1));
122         assert(m.size() == 11);
123         assert(r.second);                   // was inserted
124         assert(mv1.moved());                // was moved from
125         assert(mvkey2.moved());             // was moved from
126         assert(r.first->first.get()  == 3); // key
127         assert(r.first->second.get() == 4); // value
128     }
129 
130     {  // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
131         typedef std::map<int, Moveable> M;
132         M m;
133         M::iterator r;
134         for ( int i = 0; i < 20; i += 2 )
135             m.try_emplace ( i, Moveable(i, (double) i));
136         assert(m.size() == 10);
137         M::const_iterator it = m.find(2);
138 
139         Moveable mv1(3, 3.0);
140         for (int i=0; i < 20; i += 2)
141         {
142             r = m.try_emplace(it, i, std::move(mv1));
143             assert(m.size() == 10);
144             assert(!mv1.moved());         // was not moved from
145             assert(r->first == i);        // key
146             assert(r->second.get() == i); // value
147         }
148 
149         r = m.try_emplace(it, 3, std::move(mv1));
150         assert(m.size() == 11);
151         assert(mv1.moved());          // was moved from
152         assert(r->first == 3);        // key
153         assert(r->second.get() == 3); // value
154     }
155 
156     {  // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
157         typedef std::map<Moveable, Moveable> M;
158         M m;
159         M::iterator r;
160         for ( int i = 0; i < 20; i += 2 )
161             m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
162         assert(m.size() == 10);
163         M::const_iterator it = std::next(m.cbegin());
164 
165         Moveable mvkey1(2, 2.0);
166         Moveable mv1(4, 4.0);
167         r = m.try_emplace(it, std::move(mvkey1), std::move(mv1));
168         assert(m.size() == 10);
169         assert(!mv1.moved());        // was not moved from
170         assert(!mvkey1.moved());     // was not moved from
171         assert(r->first == mvkey1);  // key
172 
173         Moveable mvkey2(3, 3.0);
174         r = m.try_emplace(it, std::move(mvkey2), std::move(mv1));
175         assert(m.size() == 11);
176         assert(mv1.moved());          // was moved from
177         assert(mvkey2.moved());       // was moved from
178         assert(r->first.get()  == 3); // key
179         assert(r->second.get() == 4); // value
180     }
181 
182   return 0;
183 }
184