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