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++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 #include "test_macros.h"
29 
30 class Moveable
31 {
32     Moveable(const Moveable&);
33     Moveable& operator=(const Moveable&);
34 
35     int int_;
36     double double_;
37 public:
Moveable()38     Moveable() : int_(0), double_(0) {}
Moveable(int i,double d)39     Moveable(int i, double d) : int_(i), double_(d) {}
Moveable(Moveable && x)40     Moveable(Moveable&& x)
41         : int_(x.int_), double_(x.double_)
42             {x.int_ = -1; x.double_ = -1;}
operator =(Moveable && x)43     Moveable& operator=(Moveable&& x)
44         {int_ = x.int_; x.int_ = -1;
45          double_ = x.double_; x.double_ = -1;
46          return *this;
47         }
48 
operator ==(const Moveable & x) const49     bool operator==(const Moveable& x) const
50         {return int_ == x.int_ && double_ == x.double_;}
operator <(const Moveable & x) const51     bool operator<(const Moveable& x) const
52         {return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);}
53 
get() const54     int get() const {return int_;}
moved() const55     bool moved() const {return int_ == -1;}
56 };
57 
58 
main(int,char **)59 int main(int, char**)
60 {
61     { // pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
62         typedef std::map<int, Moveable> M;
63         typedef std::pair<M::iterator, bool> R;
64         M m;
65         R r;
66         for (int i = 0; i < 20; i += 2)
67             m.emplace (i, Moveable(i, (double) i));
68         assert(m.size() == 10);
69 
70         Moveable mv1(3, 3.0);
71         for (int i=0; i < 20; i += 2)
72         {
73             r = m.try_emplace(i, std::move(mv1));
74             assert(m.size() == 10);
75             assert(!r.second);              // was not inserted
76             assert(!mv1.moved());           // was not moved from
77             assert(r.first->first == i);    // key
78         }
79 
80         r = m.try_emplace(-1, std::move(mv1));
81         assert(m.size() == 11);
82         assert(r.second);                   // was inserted
83         assert(mv1.moved());                // was moved from
84         assert(r.first->first == -1);       // key
85         assert(r.first->second.get() == 3); // value
86 
87         Moveable mv2(5, 3.0);
88         r = m.try_emplace(5, std::move(mv2));
89         assert(m.size() == 12);
90         assert(r.second);                   // was inserted
91         assert(mv2.moved());                // was moved from
92         assert(r.first->first == 5);        // key
93         assert(r.first->second.get() == 5); // value
94 
95         Moveable mv3(-1, 3.0);
96         r = m.try_emplace(117, std::move(mv2));
97         assert(m.size() == 13);
98         assert(r.second);                    // was inserted
99         assert(mv2.moved());                 // was moved from
100         assert(r.first->first == 117);       // key
101         assert(r.first->second.get() == -1); // value
102     }
103 
104     {  // pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
105         typedef std::map<Moveable, Moveable> M;
106         typedef std::pair<M::iterator, bool> R;
107         M m;
108         R r;
109         for ( int i = 0; i < 20; i += 2 )
110             m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
111         assert(m.size() == 10);
112 
113         Moveable mvkey1(2, 2.0);
114         Moveable mv1(4, 4.0);
115         r = m.try_emplace(std::move(mvkey1), std::move(mv1));
116         assert(m.size() == 10);
117         assert(!r.second);                 // was not inserted
118         assert(!mv1.moved());              // was not moved from
119         assert(!mvkey1.moved());           // was not moved from
120         assert(r.first->first == mvkey1);  // key
121 
122         Moveable mvkey2(3, 3.0);
123         r = m.try_emplace(std::move(mvkey2), std::move(mv1));
124         assert(m.size() == 11);
125         assert(r.second);                   // was inserted
126         assert(mv1.moved());                // was moved from
127         assert(mvkey2.moved());             // was moved from
128         assert(r.first->first.get()  == 3); // key
129         assert(r.first->second.get() == 4); // value
130     }
131 
132     {  // iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
133         typedef std::map<int, Moveable> M;
134         M m;
135         M::iterator r;
136         for ( int i = 0; i < 20; i += 2 )
137             m.try_emplace ( i, Moveable(i, (double) i));
138         assert(m.size() == 10);
139         M::const_iterator it = m.find(2);
140 
141         Moveable mv1(3, 3.0);
142         for (int i=0; i < 20; i += 2)
143         {
144             r = m.try_emplace(it, i, std::move(mv1));
145             assert(m.size() == 10);
146             assert(!mv1.moved());         // was not moved from
147             assert(r->first == i);        // key
148             assert(r->second.get() == i); // value
149         }
150 
151         r = m.try_emplace(it, 3, std::move(mv1));
152         assert(m.size() == 11);
153         assert(mv1.moved());          // was moved from
154         assert(r->first == 3);        // key
155         assert(r->second.get() == 3); // value
156     }
157 
158     {  // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
159         typedef std::map<Moveable, Moveable> M;
160         M m;
161         M::iterator r;
162         for ( int i = 0; i < 20; i += 2 )
163             m.emplace ( Moveable(i, (double) i), Moveable(i+1, (double) i+1));
164         assert(m.size() == 10);
165         M::const_iterator it = std::next(m.cbegin());
166 
167         Moveable mvkey1(2, 2.0);
168         Moveable mv1(4, 4.0);
169         r = m.try_emplace(it, std::move(mvkey1), std::move(mv1));
170         assert(m.size() == 10);
171         assert(!mv1.moved());        // was not moved from
172         assert(!mvkey1.moved());     // was not moved from
173         assert(r->first == mvkey1);  // key
174 
175         Moveable mvkey2(3, 3.0);
176         r = m.try_emplace(it, std::move(mvkey2), std::move(mv1));
177         assert(m.size() == 11);
178         assert(mv1.moved());          // was moved from
179         assert(mvkey2.moved());       // was moved from
180         assert(r->first.get()  == 3); // key
181         assert(r->second.get() == 4); // value
182     }
183 
184   return 0;
185 }
186