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