1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Howard Hinnant 2014.
4// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
5// Software License, Version 1.0. (See accompanying file
6// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7//
8// See http://www.boost.org/libs/container for documentation.
9//
10//////////////////////////////////////////////////////////////////////////////
11//
12// This testcase is based on H. Hinnant's article "Insert vs. Emplace",
13// (http://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html)
14//
15//////////////////////////////////////////////////////////////////////////////
16#include <iostream>
17#include <boost/move/utility_core.hpp>
18#include <boost/container/vector.hpp>
19#include <boost/core/lightweight_test.hpp>
20
21class X
22{
23 int i_;
24 int* p_;
25
26 BOOST_COPYABLE_AND_MOVABLE(X)
27
28public:
29 struct special
30 {
31 unsigned c;
32 unsigned dt;
33 unsigned cc;
34 unsigned ca;
35 unsigned mc;
36 unsigned ma;
37
38 friend bool operator==(const special &l, const special &r)
39 { return l.c == r.c && l.dt == r.dt && l.cc == r.cc && l.ca == r.ca && l.mc == r.mc && l.ma == r.ma; }
40 };
41 static special sp;
42
43 X(int i, int* p)
44 : i_(i)
45 , p_(p)
46 {
47// std::cout << "X(int i, int* p)\n";
48 sp.c++;
49 }
50
51 ~X()
52 {
53// std::cout << "~X()\n";
54 sp.dt++;
55 }
56
57 X(const X& x)
58 : i_(x.i_)
59 , p_(x.p_)
60 {
61// std::cout << "X(const X& x)\n";
62 sp.cc++;
63 }
64
65 X& operator=(BOOST_COPY_ASSIGN_REF(X) x)
66 {
67
68 i_ = x.i_;
69 p_ = x.p_;
70// std::cout << "X& operator=(const X& x)\n";
71 sp.ca++;
72 return *this;
73 }
74
75 X(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
76 : i_(x.i_)
77 , p_(x.p_)
78 {
79// std::cout << "X(X&& x)\n";
80 sp.mc++;
81 }
82
83 X& operator=(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
84 {
85
86 i_ = x.i_;
87 p_ = x.p_;
88// std::cout << "X& operator=(X&& x)\n";
89 sp.ma++;
90 return *this;
91 }
92
93};
94
95std::ostream&
96operator<<(std::ostream& os, X::special const& sp)
97{
98 os << "Const: " << sp.c << '\n';
99 os << "Destr: " << sp.dt << '\n';
100 os << "CopyC: " << sp.cc << '\n';
101 os << "CopyA: " << sp.ca << '\n';
102 os << "MoveC: " << sp.mc << '\n';
103 os << "MoveA: " << sp.ma << '\n';
104 os << "Total: " << (sp.c + sp.dt + sp.cc + sp.ca + sp.mc + sp.ma) << '\n';
105 return os;
106}
107
108X::special X::sp = X::special();
109
110const X produce_const_prvalue()
111{ return X(0, 0); }
112
113int main()
114{
115 X::special insert_results;
116 X::special emplace_results;
117 {
118 boost::container::vector<X> v;
119 v.reserve(new_cap: 4);
120 v.push_back(x: X(0,0));
121 v.push_back(x: X(0,0));
122 v.push_back(x: X(0,0));
123 X x(0,0);
124 std::cout << "--insert lvalue no reallocation--\n";
125 X::sp = X::special();
126 v.insert(arg1: v.begin(), x);
127 std::cout << X::sp;
128 std::cout << "----\n";
129 insert_results = X::sp;
130 }
131 {
132 boost::container::vector<X> v;
133 v.reserve(new_cap: 4);
134 v.push_back(x: X(0,0));
135 v.push_back(x: X(0,0));
136 v.push_back(x: X(0,0));
137 X x(0,0);
138 std::cout << "--emplace lvalue no reallocation--\n";
139 X::sp = X::special();
140 v.emplace(position: v.begin(), args&: x);
141 std::cout << X::sp;
142 std::cout << "----\n";
143 emplace_results = X::sp;
144 }
145 {
146 boost::container::vector<X> v;
147 v.reserve(new_cap: 4);
148 v.push_back(x: X(0,0));
149 v.push_back(x: X(0,0));
150 v.push_back(x: X(0,0));
151 X x(0,0);
152 std::cout << "--insert xvalue no reallocation--\n";
153 X::sp = X::special();
154 v.insert(arg1: v.begin(), x: boost::move(t&: x));
155 std::cout << X::sp;
156 std::cout << "----\n";
157 insert_results = X::sp;
158 }
159 {
160 boost::container::vector<X> v;
161 v.reserve(new_cap: 4);
162 v.push_back(x: X(0,0));
163 v.push_back(x: X(0,0));
164 v.push_back(x: X(0,0));
165 X x(0,0);
166 std::cout << "--emplace xvalue no reallocation--\n";
167 X::sp = X::special();
168 v.emplace(position: v.begin(), args: boost::move(t&: x));
169 std::cout << X::sp;
170 std::cout << "----\n";
171 emplace_results = X::sp;
172 }
173 BOOST_TEST_EQ(insert_results == emplace_results, true);
174 {
175 boost::container::vector<X> v;
176 v.reserve(new_cap: 4);
177 v.push_back(x: X(0,0));
178 v.push_back(x: X(0,0));
179 v.push_back(x: X(0,0));
180 X x(0,0);
181 std::cout << "--emplace const prvalue no reallocation--\n";
182 X::sp = X::special();
183 v.emplace(position: v.begin(), args: produce_const_prvalue());
184 std::cout << X::sp;
185 std::cout << "----\n";
186 emplace_results = X::sp;
187 }
188 {
189 boost::container::vector<X> v;
190 v.reserve(new_cap: 4);
191 v.push_back(x: X(0,0));
192 v.push_back(x: X(0,0));
193 v.push_back(x: X(0,0));
194 X x(0,0);
195 std::cout << "--emplace const prvalue no reallocation--\n";
196 X::sp = X::special();
197 v.insert(arg1: v.begin(), x: produce_const_prvalue());
198 std::cout << X::sp;
199 std::cout << "----\n";
200 insert_results = X::sp;
201 }
202 BOOST_TEST_EQ(insert_results == emplace_results, true);
203 {
204 boost::container::vector<X> v;
205 v.reserve(new_cap: 4);
206 v.push_back(x: X(0,0));
207 v.push_back(x: X(0,0));
208 v.push_back(x: X(0,0));
209 std::cout << "--insert rvalue no reallocation--\n";
210 X::sp = X::special();
211 v.insert(arg1: v.begin(), x: X(0,0));
212 std::cout << X::sp;
213 std::cout << "----\n";
214 insert_results = X::sp;
215 }
216 {
217 boost::container::vector<X> v;
218 v.reserve(new_cap: 4);
219 v.push_back(x: X(0,0));
220 v.push_back(x: X(0,0));
221 v.push_back(x: X(0,0));
222 std::cout << "--emplace rvalue no reallocation--\n";
223 X::sp = X::special();
224 v.emplace(position: v.begin(), args: X(0,0));
225 std::cout << X::sp;
226 std::cout << "----\n";
227 emplace_results = X::sp;
228 }
229 //With emulated move semantics an extra copy is unavoidable
230 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
231 BOOST_TEST_EQ(insert_results == emplace_results, true);
232 #endif
233 {
234 boost::container::vector<X> v;
235 v.reserve(new_cap: 3);
236 v.push_back(x: X(0,0));
237 v.push_back(x: X(0,0));
238 v.push_back(x: X(0,0));
239 X x(0,0);
240 std::cout << "--insert lvalue reallocation--\n";
241 X::sp = X::special();
242 v.insert(arg1: v.begin(), x);
243 std::cout << X::sp;
244 std::cout << "----\n";
245 insert_results = X::sp;
246 }
247 {
248 boost::container::vector<X> v;
249 v.reserve(new_cap: 3);
250 v.push_back(x: X(0,0));
251 v.push_back(x: X(0,0));
252 v.push_back(x: X(0,0));
253 X x(0,0);
254 std::cout << "--emplace lvalue reallocation--\n";
255 X::sp = X::special();
256 v.emplace(position: v.begin(), args&: x);
257 std::cout << X::sp;
258 std::cout << "----\n";
259 emplace_results = X::sp;
260 }
261 BOOST_TEST_EQ(insert_results == emplace_results, true);
262 {
263 boost::container::vector<X> v;
264 v.reserve(new_cap: 3);
265 v.push_back(x: X(0,0));
266 v.push_back(x: X(0,0));
267 v.push_back(x: X(0,0));
268 X x(0,0);
269 std::cout << "--insert xvalue reallocation--\n";
270 X::sp = X::special();
271 v.insert(arg1: v.begin(), x: boost::move(t&: x));
272 std::cout << X::sp;
273 std::cout << "----\n";
274 insert_results = X::sp;
275 }
276 {
277 boost::container::vector<X> v;
278 v.reserve(new_cap: 3);
279 v.push_back(x: X(0,0));
280 v.push_back(x: X(0,0));
281 v.push_back(x: X(0,0));
282 X x(0,0);
283 std::cout << "--emplace xvalue reallocation--\n";
284 X::sp = X::special();
285 v.emplace(position: v.begin(), args: boost::move(t&: x));
286 std::cout << X::sp;
287 std::cout << "----\n";
288 emplace_results = X::sp;
289 }
290 BOOST_TEST_EQ(insert_results == emplace_results, true);
291 {
292 boost::container::vector<X> v;
293 v.reserve(new_cap: 3);
294 v.push_back(x: X(0,0));
295 v.push_back(x: X(0,0));
296 v.push_back(x: X(0,0));
297 std::cout << "--insert rvalue reallocation--\n";
298 X::sp = X::special();
299 v.insert(arg1: v.begin(), x: X(0,0));
300 std::cout << X::sp;
301 std::cout << "----\n";
302 insert_results = X::sp;
303 }
304 {
305 boost::container::vector<X> v;
306 v.reserve(new_cap: 3);
307 v.push_back(x: X(0,0));
308 v.push_back(x: X(0,0));
309 v.push_back(x: X(0,0));
310 std::cout << "--emplace rvalue reallocation--\n";
311 X::sp = X::special();
312 v.emplace(position: v.begin(), args: X(0,0));
313 std::cout << X::sp;
314 std::cout << "----\n";
315 emplace_results = X::sp;
316 }
317 //With emulated move semantics an extra copy is unavoidable
318 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
319 BOOST_TEST_EQ(insert_results == emplace_results, true);
320 #endif
321 {
322 boost::container::vector<X> v;
323 v.reserve(new_cap: 4);
324 v.push_back(x: X(0,0));
325 v.push_back(x: X(0,0));
326 v.push_back(x: X(0,0));
327 X x(0,0);
328 std::cout << "--push_back lvalue no reallocation--\n";
329 X::sp = X::special();
330 v.push_back(x);
331 std::cout << X::sp;
332 std::cout << "----\n";
333 insert_results = X::sp;
334 }
335 {
336 boost::container::vector<X> v;
337 v.reserve(new_cap: 4);
338 v.push_back(x: X(0,0));
339 v.push_back(x: X(0,0));
340 v.push_back(x: X(0,0));
341 X x(0,0);
342 std::cout << "--emplace_back lvalue no reallocation--\n";
343 X::sp = X::special();
344 v.emplace_back(args&: x);
345 std::cout << X::sp;
346 std::cout << "----\n";
347 emplace_results = X::sp;
348 }
349 BOOST_TEST_EQ(insert_results == emplace_results, true);
350 {
351 boost::container::vector<X> v;
352 v.reserve(new_cap: 4);
353 v.push_back(x: X(0,0));
354 v.push_back(x: X(0,0));
355 v.push_back(x: X(0,0));
356 X x(0,0);
357 std::cout << "--push_back xvalue no reallocation--\n";
358 X::sp = X::special();
359 v.push_back(x: boost::move(t&: x));
360 std::cout << X::sp;
361 std::cout << "----\n";
362 insert_results = X::sp;
363 }
364 {
365 boost::container::vector<X> v;
366 v.reserve(new_cap: 4);
367 v.push_back(x: X(0,0));
368 v.push_back(x: X(0,0));
369 v.push_back(x: X(0,0));
370 X x(0,0);
371 std::cout << "--emplace_back xvalue no reallocation--\n";
372 X::sp = X::special();
373 v.emplace_back(args: boost::move(t&: x));
374 std::cout << X::sp;
375 std::cout << "----\n";
376 emplace_results = X::sp;
377 }
378 BOOST_TEST_EQ(insert_results == emplace_results, true);
379 {
380 boost::container::vector<X> v;
381 v.reserve(new_cap: 4);
382 v.push_back(x: X(0,0));
383 v.push_back(x: X(0,0));
384 v.push_back(x: X(0,0));
385 std::cout << "--push_back rvalue no reallocation--\n";
386 X::sp = X::special();
387 v.push_back(x: X(0,0));
388 std::cout << X::sp;
389 std::cout << "----\n";
390 insert_results = X::sp;
391 }
392 {
393 boost::container::vector<X> v;
394 v.reserve(new_cap: 4);
395 v.push_back(x: X(0,0));
396 v.push_back(x: X(0,0));
397 v.push_back(x: X(0,0));
398 std::cout << "--emplace_back rvalue no reallocation--\n";
399 X::sp = X::special();
400 v.emplace_back(args: X(0,0));
401 std::cout << X::sp;
402 std::cout << "----\n";
403 emplace_results = X::sp;
404 }
405 //With emulated move semantics an extra copy is unavoidable
406 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
407 BOOST_TEST_EQ(insert_results == emplace_results, true);
408 #endif
409 {
410 boost::container::vector<X> v;
411 v.reserve(new_cap: 3);
412 v.push_back(x: X(0,0));
413 v.push_back(x: X(0,0));
414 v.push_back(x: X(0,0));
415 X x(0,0);
416 std::cout << "--push_back lvalue reallocation--\n";
417 X::sp = X::special();
418 v.push_back(x);
419 std::cout << X::sp;
420 std::cout << "----\n";
421 insert_results = X::sp;
422 }
423 {
424 boost::container::vector<X> v;
425 v.reserve(new_cap: 3);
426 v.push_back(x: X(0,0));
427 v.push_back(x: X(0,0));
428 v.push_back(x: X(0,0));
429 X x(0,0);
430 std::cout << "--emplace_back lvalue reallocation--\n";
431 X::sp = X::special();
432 v.emplace_back(args&: x);
433 std::cout << X::sp;
434 std::cout << "----\n";
435 emplace_results = X::sp;
436 }
437 BOOST_TEST_EQ(insert_results == emplace_results, true);
438 {
439 boost::container::vector<X> v;
440 v.reserve(new_cap: 3);
441 v.push_back(x: X(0,0));
442 v.push_back(x: X(0,0));
443 v.push_back(x: X(0,0));
444 X x(0,0);
445 std::cout << "--push_back xvalue reallocation--\n";
446 X::sp = X::special();
447 v.push_back(x: boost::move(t&: x));
448 std::cout << X::sp;
449 std::cout << "----\n";
450 insert_results = X::sp;
451 }
452 {
453 boost::container::vector<X> v;
454 v.reserve(new_cap: 3);
455 v.push_back(x: X(0,0));
456 v.push_back(x: X(0,0));
457 v.push_back(x: X(0,0));
458 X x(0,0);
459 std::cout << "--emplace_back xvalue reallocation--\n";
460 X::sp = X::special();
461 v.emplace_back(args: boost::move(t&: x));
462 std::cout << X::sp;
463 std::cout << "----\n";
464 emplace_results = X::sp;
465 }
466 BOOST_TEST_EQ(insert_results == emplace_results, true);
467 {
468 boost::container::vector<X> v;
469 v.reserve(new_cap: 3);
470 v.push_back(x: X(0,0));
471 v.push_back(x: X(0,0));
472 v.push_back(x: X(0,0));
473 std::cout << "--push_back rvalue reallocation--\n";
474 X::sp = X::special();
475 v.push_back(x: X(0,0));
476 std::cout << X::sp;
477 std::cout << "----\n";
478 insert_results = X::sp;
479 }
480 {
481 boost::container::vector<X> v;
482 v.reserve(new_cap: 3);
483 v.push_back(x: X(0,0));
484 v.push_back(x: X(0,0));
485 v.push_back(x: X(0,0));
486 std::cout << "--emplace_back rvalue reallocation--\n";
487 X::sp = X::special();
488 v.emplace_back(args: X(0,0));
489 std::cout << X::sp;
490 std::cout << "----\n";
491 emplace_results = X::sp;
492 }
493 //With emulated move semantics an extra copy is unavoidable
494 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
495 BOOST_TEST_EQ(insert_results == emplace_results, true);
496 #endif
497 return boost::report_errors();
498}
499

source code of boost/libs/container/test/insert_vs_emplace_test.cpp