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