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