1 // { dg-do run { target c++11 } }
2
3 // The class X and test code is by by Howard Hinnant and used under a
4 // Creative Commons Attribution 4.0 International License.
5 // http://creativecommons.org/licenses/by/4.0/
6 // https://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html
7 //
8 // The original code was reformatted and modified to use the VERIFY macro
9 // instead of writing to standard output.
10
11 #include <testsuite_hooks.h>
12 #include <vector>
13 #include <iostream>
14
15 class X
16 {
17 int i_;
18 int* p_;
19
20 public:
21 struct special
22 {
23 unsigned c;
24 unsigned dt;
25 unsigned cc;
26 unsigned ca;
27 unsigned mc;
28 unsigned ma;
29 };
30 static special sp;
31
X(int i,int * p)32 X(int i, int* p)
33 : i_(i)
34 , p_(p)
35 {
36 // std::cout << "X(int i, int* p)\n";
37 sp.c++;
38 }
39
~X()40 ~X()
41 {
42 // std::cout << "~X()\n";
43 sp.dt++;
44 }
45
X(const X & x)46 X(const X& x)
47 : i_(x.i_)
48 , p_(x.p_)
49 {
50 // std::cout << "X(const X& x)\n";
51 sp.cc++;
52 }
53
operator =(const X & x)54 X& operator=(const X& x)
55 {
56
57 i_ = x.i_;
58 p_ = x.p_;
59 // std::cout << "X& operator=(const X& x)\n";
60 sp.ca++;
61 return *this;
62 }
63
X(X && x)64 X(X&& x) noexcept
65 : i_(x.i_)
66 , p_(x.p_)
67 {
68 // std::cout << "X(X&& x)\n";
69 sp.mc++;
70 }
71
operator =(X && x)72 X& operator=(X&& x) noexcept
73 {
74
75 i_ = x.i_;
76 p_ = x.p_;
77 // std::cout << "X& operator=(X&& x)\n";
78 sp.ma++;
79 return *this;
80 }
81
82 };
83
84 std::ostream&
operator <<(std::ostream & os,X::special const & sp)85 operator<<(std::ostream& os, X::special const& sp)
86 {
87 os << sp.c << '\n';
88 os << sp.dt << '\n';
89 os << sp.cc << '\n';
90 os << sp.ca << '\n';
91 os << sp.mc << '\n';
92 os << sp.ma << '\n';
93 return os;
94 }
95
96 X::special X::sp{};
97
98 bool
operator ==(const X::special & lhs,const X::special & rhs)99 operator==(const X::special& lhs, const X::special& rhs)
100 {
101 return lhs.c == rhs.c && lhs.dt == rhs.dt
102 && lhs.cc == rhs.cc && lhs.ca == rhs.ca
103 && lhs.mc == rhs.mc && lhs.ma == rhs.ma;
104 }
105
106 // Verify that insert and emplace are equally efficient.
107 // Also verify exact number of operations (which are specific to this
108 // implementation) in order to catch any regressions.
109
110 // insert vs emplace lvalue no reallocation
111 void
test01()112 test01()
113 {
114 const X::special expected{ 0, 1, 1, 0, 1, 3 };
115 X::special ins, emp;
116 {
117 std::vector<X> v;
118 v.reserve(4);
119 v.push_back(X(0,0));
120 v.push_back(X(0,0));
121 v.push_back(X(0,0));
122 X x{0,0};
123 // std::cout << "--insert lvalue no reallocation--\n";
124 X::sp = {};
125 v.insert(v.begin(), x);
126 // std::cout << X::sp;
127 // std::cout << "----\n";
128 ins = X::sp;
129 }
130 {
131 std::vector<X> v;
132 v.reserve(4);
133 v.push_back(X(0,0));
134 v.push_back(X(0,0));
135 v.push_back(X(0,0));
136 X x{0,0};
137 // std::cout << "--emplace lvalue no reallocation--\n";
138 X::sp = {};
139 v.emplace(v.begin(), x);
140 // std::cout << X::sp;
141 // std::cout << "----\n";
142 emp = X::sp;
143 }
144 VERIFY( ins == emp );
145 VERIFY( ins == expected );
146 }
147
148 // insert vs emplace xvalue no reallocation
149 void
test02()150 test02()
151 {
152 const X::special expected{ 0, 0, 0, 0, 1, 3 };
153 X::special ins, emp;
154 {
155 std::vector<X> v;
156 v.reserve(4);
157 v.push_back(X(0,0));
158 v.push_back(X(0,0));
159 v.push_back(X(0,0));
160 X x{0,0};
161 // std::cout << "--insert xvalue no reallocation--\n";
162 X::sp = {};
163 v.insert(v.begin(), std::move(x));
164 // std::cout << X::sp;
165 // std::cout << "----\n";
166 ins = X::sp;
167 }
168 {
169 std::vector<X> v;
170 v.reserve(4);
171 v.push_back(X(0,0));
172 v.push_back(X(0,0));
173 v.push_back(X(0,0));
174 X x{0,0};
175 // std::cout << "--emplace xvalue no reallocation--\n";
176 X::sp = {};
177 v.emplace(v.begin(), std::move(x));
178 // std::cout << X::sp;
179 // std::cout << "----\n";
180 emp = X::sp;
181 }
182 VERIFY( ins == emp );
183 VERIFY( ins == expected );
184 }
185
186 // insert vs emplace rvalue no reallocation
187 void
test03()188 test03()
189 {
190 const X::special expected{ 1, 1, 0, 0, 1, 3 };
191 X::special ins, emp;
192 {
193 std::vector<X> v;
194 v.reserve(4);
195 v.push_back(X(0,0));
196 v.push_back(X(0,0));
197 v.push_back(X(0,0));
198 // std::cout << "--insert rvalue no reallocation--\n";
199 X::sp = {};
200 v.insert(v.begin(), X{0,0});
201 // std::cout << X::sp;
202 // std::cout << "----\n";
203 ins = X::sp;
204 }
205 {
206 std::vector<X> v;
207 v.reserve(4);
208 v.push_back(X(0,0));
209 v.push_back(X(0,0));
210 v.push_back(X(0,0));
211 // std::cout << "--emplace rvalue no reallocation--\n";
212 X::sp = {};
213 v.emplace(v.begin(), X{0,0});
214 // std::cout << X::sp;
215 // std::cout << "----\n";
216 emp = X::sp;
217 }
218 VERIFY( ins == emp );
219 VERIFY( ins == expected );
220 }
221
222 // insert vs emplace lvalue reallocation
223 void
test04()224 test04()
225 {
226 const X::special expected{ 0, 3, 1, 0, 3, 0 };
227 X::special ins, emp;
228 {
229 std::vector<X> v;
230 v.reserve(3);
231 v.push_back(X(0,0));
232 v.push_back(X(0,0));
233 v.push_back(X(0,0));
234 X x{0,0};
235 // std::cout << "--insert lvalue reallocation--\n";
236 X::sp = {};
237 v.insert(v.begin(), x);
238 // std::cout << X::sp;
239 // std::cout << "----\n";
240 ins = X::sp;
241 }
242 {
243 std::vector<X> v;
244 v.reserve(3);
245 v.push_back(X(0,0));
246 v.push_back(X(0,0));
247 v.push_back(X(0,0));
248 X x{0,0};
249 // std::cout << "--emplace lvalue reallocation--\n";
250 X::sp = {};
251 v.emplace(v.begin(), x);
252 // std::cout << X::sp;
253 // std::cout << "----\n";
254 emp = X::sp;
255 }
256 VERIFY( ins == emp );
257 VERIFY( ins == expected );
258 }
259
260 // insert vs emplace xvalue reallocation
261 void
test05()262 test05()
263 {
264 const X::special expected{ 0, 3, 0, 0, 4, 0 };
265 X::special ins, emp;
266 {
267 std::vector<X> v;
268 v.reserve(3);
269 v.push_back(X(0,0));
270 v.push_back(X(0,0));
271 v.push_back(X(0,0));
272 X x{0,0};
273 // std::cout << "--insert xvalue reallocation--\n";
274 X::sp = {};
275 v.insert(v.begin(), std::move(x));
276 // std::cout << X::sp;
277 // std::cout << "----\n";
278 ins = X::sp;
279 }
280 {
281 std::vector<X> v;
282 v.reserve(3);
283 v.push_back(X(0,0));
284 v.push_back(X(0,0));
285 v.push_back(X(0,0));
286 X x{0,0};
287 // std::cout << "--emplace xvalue reallocation--\n";
288 X::sp = {};
289 v.emplace(v.begin(), std::move(x));
290 // std::cout << X::sp;
291 // std::cout << "----\n";
292 emp = X::sp;
293 }
294 VERIFY( ins == emp );
295 VERIFY( ins == expected );
296 }
297
298 // insert vs emplace rvalue reallocation
299 void
test06()300 test06()
301 {
302 const X::special expected{ 1, 4, 0, 0, 4, 0 };
303 X::special ins, emp;
304 {
305 std::vector<X> v;
306 v.reserve(3);
307 v.push_back(X(0,0));
308 v.push_back(X(0,0));
309 v.push_back(X(0,0));
310 // std::cout << "--insert rvalue reallocation--\n";
311 X::sp = {};
312 v.insert(v.begin(), X{0,0});
313 // std::cout << X::sp;
314 // std::cout << "----\n";
315 ins = X::sp;
316 }
317 {
318 std::vector<X> v;
319 v.reserve(3);
320 v.push_back(X(0,0));
321 v.push_back(X(0,0));
322 v.push_back(X(0,0));
323 // std::cout << "--emplace rvalue reallocation--\n";
324 X::sp = {};
325 v.emplace(v.begin(), X{0,0});
326 // std::cout << X::sp;
327 // std::cout << "----\n";
328 emp = X::sp;
329 }
330 VERIFY( ins == emp );
331 VERIFY( ins == expected );
332 }
333
334 // push_back vs emplace_back lvalue no reallocation
335 void
test07()336 test07()
337 {
338 const X::special expected{ 0, 0, 1, 0, 0, 0 };
339 X::special ins, emp;
340 {
341 std::vector<X> v;
342 v.reserve(4);
343 v.push_back(X(0,0));
344 v.push_back(X(0,0));
345 v.push_back(X(0,0));
346 X x{0,0};
347 // std::cout << "--push_back lvalue no reallocation--\n";
348 X::sp = {};
349 v.push_back(x);
350 // std::cout << X::sp;
351 // std::cout << "----\n";
352 ins = X::sp;
353 }
354 {
355 std::vector<X> v;
356 v.reserve(4);
357 v.push_back(X(0,0));
358 v.push_back(X(0,0));
359 v.push_back(X(0,0));
360 X x{0,0};
361 // std::cout << "--emplace_back lvalue no reallocation--\n";
362 X::sp = {};
363 v.emplace_back(x);
364 // std::cout << X::sp;
365 // std::cout << "----\n";
366 emp = X::sp;
367 }
368 VERIFY( ins == emp );
369 VERIFY( ins == expected );
370 }
371
372 // push_back vs emplace_back xvalue no reallocation
373 void
test08()374 test08()
375 {
376 const X::special expected{ 0, 0, 0, 0, 1, 0 };
377 X::special ins, emp;
378 {
379 std::vector<X> v;
380 v.reserve(4);
381 v.push_back(X(0,0));
382 v.push_back(X(0,0));
383 v.push_back(X(0,0));
384 X x{0,0};
385 // std::cout << "--push_back xvalue no reallocation--\n";
386 X::sp = {};
387 v.push_back(std::move(x));
388 // std::cout << X::sp;
389 // std::cout << "----\n";
390 ins = X::sp;
391 }
392 {
393 std::vector<X> v;
394 v.reserve(4);
395 v.push_back(X(0,0));
396 v.push_back(X(0,0));
397 v.push_back(X(0,0));
398 X x{0,0};
399 // std::cout << "--emplace_back xvalue no reallocation--\n";
400 X::sp = {};
401 v.emplace_back(std::move(x));
402 // std::cout << X::sp;
403 // std::cout << "----\n";
404 emp = X::sp;
405 }
406 VERIFY( ins == emp );
407 VERIFY( ins == expected );
408 }
409
410 // push_back vs emplace_back rvalue no reallocation
411 void
test09()412 test09()
413 {
414 const X::special expected{ 1, 1, 0, 0, 1, 0 };
415 X::special ins, emp;
416 {
417 std::vector<X> v;
418 v.reserve(4);
419 v.push_back(X(0,0));
420 v.push_back(X(0,0));
421 v.push_back(X(0,0));
422 // std::cout << "--push_back rvalue no reallocation--\n";
423 X::sp = {};
424 v.push_back(X{0,0});
425 // std::cout << X::sp;
426 // std::cout << "----\n";
427 ins = X::sp;
428 }
429 {
430 std::vector<X> v;
431 v.reserve(4);
432 v.push_back(X(0,0));
433 v.push_back(X(0,0));
434 v.push_back(X(0,0));
435 // std::cout << "--emplace_back rvalue no reallocation--\n";
436 X::sp = {};
437 v.emplace_back(X{0,0});
438 // std::cout << X::sp;
439 // std::cout << "----\n";
440 emp = X::sp;
441 }
442 VERIFY( ins == emp );
443 VERIFY( ins == expected );
444 }
445
446 // push_back vs emplace_back lvalue reallocation
447 void
test10()448 test10()
449 {
450 const X::special expected{ 0, 3, 1, 0, 3, 0 };
451 X::special ins, emp;
452 {
453 std::vector<X> v;
454 v.reserve(3);
455 v.push_back(X(0,0));
456 v.push_back(X(0,0));
457 v.push_back(X(0,0));
458 X x{0,0};
459 // std::cout << "--push_back lvalue reallocation--\n";
460 X::sp = {};
461 v.push_back(x);
462 // std::cout << X::sp;
463 // std::cout << "----\n";
464 ins = X::sp;
465 }
466 {
467 std::vector<X> v;
468 v.reserve(3);
469 v.push_back(X(0,0));
470 v.push_back(X(0,0));
471 v.push_back(X(0,0));
472 X x{0,0};
473 // std::cout << "--emplace_back lvalue reallocation--\n";
474 X::sp = {};
475 v.emplace_back(x);
476 // std::cout << X::sp;
477 // std::cout << "----\n";
478 emp = X::sp;
479 }
480 VERIFY( ins == emp );
481 VERIFY( ins == expected );
482 }
483
484 // push_back vs emplace_back xvalue reallocation
485 void
test11()486 test11()
487 {
488 const X::special expected{ 0, 3, 0, 0, 4, 0 };
489 X::special ins, emp;
490 {
491 std::vector<X> v;
492 v.reserve(3);
493 v.push_back(X(0,0));
494 v.push_back(X(0,0));
495 v.push_back(X(0,0));
496 X x{0,0};
497 // std::cout << "--push_back xvalue reallocation--\n";
498 X::sp = {};
499 v.push_back(std::move(x));
500 // std::cout << X::sp;
501 // std::cout << "----\n";
502 ins = X::sp;
503 }
504 {
505 std::vector<X> v;
506 v.reserve(3);
507 v.push_back(X(0,0));
508 v.push_back(X(0,0));
509 v.push_back(X(0,0));
510 X x{0,0};
511 // std::cout << "--emplace_back xvalue reallocation--\n";
512 X::sp = {};
513 v.emplace_back(std::move(x));
514 // std::cout << X::sp;
515 // std::cout << "----\n";
516 emp = X::sp;
517 }
518 VERIFY( ins == emp );
519 VERIFY( ins == expected );
520 }
521
522 // push_back vs emplace_back rvalue reallocation
523 void
test12()524 test12()
525 {
526 const X::special expected{ 1, 4, 0, 0, 4, 0 };
527 X::special ins, emp;
528 {
529 std::vector<X> v;
530 v.reserve(3);
531 v.push_back(X(0,0));
532 v.push_back(X(0,0));
533 v.push_back(X(0,0));
534 // std::cout << "--push_back rvalue reallocation--\n";
535 X::sp = {};
536 v.push_back(X{0,0});
537 // std::cout << X::sp;
538 // std::cout << "----\n";
539 ins = X::sp;
540 }
541 {
542 std::vector<X> v;
543 v.reserve(3);
544 v.push_back(X(0,0));
545 v.push_back(X(0,0));
546 v.push_back(X(0,0));
547 // std::cout << "--emplace_back rvalue reallocation--\n";
548 X::sp = {};
549 v.emplace_back(X{0,0});
550 // std::cout << X::sp;
551 // std::cout << "----\n";
552 emp = X::sp;
553 }
554 VERIFY( ins == emp );
555 VERIFY( ins == expected );
556 }
557
558 int
main()559 main()
560 {
561 test01();
562 test02();
563 test03();
564 test04();
565 test05();
566 test06();
567 test07();
568 test08();
569 test09();
570 test10();
571 test11();
572 test12();
573 }
574