1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2008. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/container for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
11#define BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
12
13#include <iostream>
14#include <typeinfo>
15#include <boost/container/detail/config_begin.hpp>
16#include <boost/container/detail/workaround.hpp>
17#include <boost/container/detail/mpl.hpp>
18#include <boost/move/utility_core.hpp>
19#include <boost/container/detail/type_traits.hpp>
20#include <boost/move/detail/force_ptr.hpp> //adl_move_swap
21
22namespace boost{
23namespace container {
24namespace test{
25
26class EmplaceInt
27{
28 BOOST_MOVABLE_BUT_NOT_COPYABLE(EmplaceInt)
29
30 public:
31 EmplaceInt(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0)
32 : a_(a), b_(b), c_(c), d_(d), e_(e)
33 {}
34
35 EmplaceInt(BOOST_RV_REF(EmplaceInt) o)
36 : a_(o.a_), b_(o.b_), c_(o.c_), d_(o.d_), e_(o.e_)
37 {}
38
39 EmplaceInt& operator=(BOOST_RV_REF(EmplaceInt) o)
40 {
41 this->a_ = o.a_;
42 this->b_ = o.b_;
43 this->c_ = o.c_;
44 this->d_ = o.d_;
45 this->e_ = o.e_;
46 return *this;
47 }
48
49 friend bool operator==(const EmplaceInt &l, const EmplaceInt &r)
50 {
51 return l.a_ == r.a_ &&
52 l.b_ == r.b_ &&
53 l.c_ == r.c_ &&
54 l.d_ == r.d_ &&
55 l.e_ == r.e_;
56 }
57
58 friend bool operator<(const EmplaceInt &l, const EmplaceInt &r)
59 { return l.sum() < r.sum(); }
60
61 friend bool operator>(const EmplaceInt &l, const EmplaceInt &r)
62 { return l.sum() > r.sum(); }
63
64 friend bool operator!=(const EmplaceInt &l, const EmplaceInt &r)
65 { return !(l == r); }
66
67 friend std::size_t hash_value(const EmplaceInt &v)
68 { return std::size_t(v.a_); }
69
70 friend std::ostream &operator <<(std::ostream &os, const EmplaceInt &v)
71 {
72 os << "EmplaceInt: " << v.a_ << ' ' << v.b_ << ' ' << v.c_ << ' ' << v.d_ << ' ' << v.e_;
73 return os;
74 }
75
76 ~EmplaceInt()
77 { a_ = b_ = c_ = d_ = e_ = 0; }
78
79 //private:
80 int sum() const
81 { return this->a_ + this->b_ + this->c_ + this->d_ + this->e_; }
82
83 int a_, b_, c_, d_, e_;
84 int padding[6];
85};
86
87
88} //namespace test {
89
90namespace test {
91
92enum EmplaceOptions{
93 EMPLACE_BACK = 1 << 0,
94 EMPLACE_FRONT = 1 << 1,
95 EMPLACE_BEFORE = 1 << 2,
96 EMPLACE_AFTER = 1 << 3,
97 EMPLACE_ASSOC = 1 << 4,
98 EMPLACE_HINT = 1 << 5,
99 EMPLACE_ASSOC_PAIR = 1 << 6,
100 EMPLACE_HINT_PAIR = 1 << 7
101};
102
103template<class Container>
104bool test_expected_container(const Container &ec, const EmplaceInt *Expected, unsigned int only_first_n, unsigned int cont_offset = 0)
105{
106 typedef typename Container::const_iterator const_iterator;
107 const_iterator itb(ec.begin()), ite(ec.end());
108 unsigned int cur = 0;
109 if(cont_offset > ec.size()){
110 return false;
111 }
112 if(only_first_n > (ec.size() - cont_offset)){
113 return false;
114 }
115 while(cont_offset--){
116 ++itb;
117 }
118 for(; itb != ite && only_first_n--; ++itb, ++cur){
119 const EmplaceInt & cr = *itb;
120 if(cr != Expected[cur]){
121 return false;
122 }
123 }
124 return true;
125}
126
127template<class Container>
128bool test_expected_container(const Container &ec, const std::pair<EmplaceInt, EmplaceInt> *Expected, unsigned int only_first_n)
129{
130 typedef typename Container::const_iterator const_iterator;
131 const_iterator itb(ec.begin()), ite(ec.end());
132 unsigned int cur = 0;
133 if(only_first_n > ec.size()){
134 return false;
135 }
136 for(; itb != ite && only_first_n--; ++itb, ++cur){
137 if(itb->first != Expected[cur].first){
138 std::cout << "Error in first: " << itb->first << ' ' << Expected[cur].first << std::endl;
139 return false;
140
141 }
142 else if(itb->second != Expected[cur].second){
143 std::cout << "Error in second: " << itb->second << ' ' << Expected[cur].second << std::endl;
144 return false;
145 }
146 }
147 return true;
148}
149
150typedef std::pair<EmplaceInt, EmplaceInt> EmplaceIntPair;
151static boost::container::dtl::aligned_storage<sizeof(EmplaceIntPair)*10>::type pair_storage;
152
153static EmplaceIntPair* initialize_emplace_int_pair()
154{
155 EmplaceIntPair* ret = move_detail::force_ptr<EmplaceIntPair*>(p: &pair_storage);
156 for(unsigned int i = 0; i != 10; ++i){
157 new(&ret->first)EmplaceInt();
158 new(&ret->second)EmplaceInt();
159 }
160 return ret;
161}
162
163static EmplaceIntPair * expected_pair = initialize_emplace_int_pair();
164
165
166template<class Container>
167bool test_emplace_back(dtl::true_)
168{
169 std::cout << "Starting test_emplace_back." << std::endl << " Class: "
170 << typeid(Container).name() << std::endl;
171 static EmplaceInt expected [10];
172
173 {
174 new(&expected [0]) EmplaceInt();
175 new(&expected [1]) EmplaceInt(1);
176 new(&expected [2]) EmplaceInt(1, 2);
177 new(&expected [3]) EmplaceInt(1, 2, 3);
178 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
179 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
180 Container c;
181 typedef typename Container::reference reference;
182 {
183 reference r = c.emplace_back();
184 if(&r != &c.back() && !test_expected_container(c, &expected[0], 1)){
185 return false;
186 }
187 }
188 {
189 reference r = c.emplace_back(1);
190 if(&r != &c.back() && !test_expected_container(c, &expected[0], 2)){
191 return false;
192 }
193 }
194 c.emplace_back(1, 2);
195 if(!test_expected_container(c, &expected[0], 3)){
196 return false;
197 }
198 c.emplace_back(1, 2, 3);
199 if(!test_expected_container(c, &expected[0], 4)){
200 return false;
201 }
202 c.emplace_back(1, 2, 3, 4);
203 if(!test_expected_container(c, &expected[0], 5)){
204 return false;
205 }
206 c.emplace_back(1, 2, 3, 4, 5);
207 if(!test_expected_container(c, &expected[0], 6)){
208 return false;
209 }
210 }
211 std::cout << "...OK" << std::endl;
212 return true;
213}
214
215template<class Container>
216bool test_emplace_back(dtl::false_)
217{ return true; }
218
219template<class Container>
220bool test_emplace_front(dtl::true_)
221{
222 std::cout << "Starting test_emplace_front." << std::endl << " Class: "
223 << typeid(Container).name() << std::endl;
224 static EmplaceInt expected [10];
225 {
226 new(&expected [0]) EmplaceInt(1, 2, 3, 4, 5);
227 new(&expected [1]) EmplaceInt(1, 2, 3, 4);
228 new(&expected [2]) EmplaceInt(1, 2, 3);
229 new(&expected [3]) EmplaceInt(1, 2);
230 new(&expected [4]) EmplaceInt(1);
231 new(&expected [5]) EmplaceInt();
232 Container c;
233 typedef typename Container::reference reference;
234 {
235 reference r = c.emplace_front();
236 if(&r != &c.front() && !test_expected_container(c, &expected[0] + 5, 1)){
237 return false;
238 }
239 }
240 {
241 reference r = c.emplace_front(1);
242 if(&r != &c.front() && !test_expected_container(c, &expected[0] + 4, 2)){
243 return false;
244 }
245 }
246 c.emplace_front(1, 2);
247 if(!test_expected_container(c, &expected[0] + 3, 3)){
248 return false;
249 }
250 c.emplace_front(1, 2, 3);
251 if(!test_expected_container(c, &expected[0] + 2, 4)){
252 return false;
253 }
254 c.emplace_front(1, 2, 3, 4);
255 if(!test_expected_container(c, &expected[0] + 1, 5)){
256 return false;
257 }
258 c.emplace_front(1, 2, 3, 4, 5);
259 if(!test_expected_container(c, &expected[0] + 0, 6)){
260 return false;
261 }
262 }
263 std::cout << "...OK" << std::endl;
264 return true;
265}
266
267template<class Container>
268bool test_emplace_front(dtl::false_)
269{ return true; }
270
271template<class Container>
272bool test_emplace_before(dtl::true_)
273{
274 std::cout << "Starting test_emplace_before." << std::endl << " Class: "
275 << typeid(Container).name() << std::endl;
276 static EmplaceInt expected [10];
277 {
278 new(&expected [0]) EmplaceInt();
279 new(&expected [1]) EmplaceInt(1);
280 new(&expected [2]) EmplaceInt();
281 Container c;
282 c.emplace(c.cend(), 1);
283 c.emplace(c.cbegin());
284 if(!test_expected_container(c, &expected[0], 2)){
285 return false;
286 }
287 c.emplace(c.cend());
288 if(!test_expected_container(c, &expected[0], 3)){
289 return false;
290 }
291 }
292 {
293 new(&expected [0]) EmplaceInt();
294 new(&expected [1]) EmplaceInt(1);
295 new(&expected [2]) EmplaceInt(1, 2);
296 new(&expected [3]) EmplaceInt(1, 2, 3);
297 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
298 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
299 //emplace_front-like
300 Container c;
301 c.emplace(c.cbegin(), 1, 2, 3, 4, 5);
302 c.emplace(c.cbegin(), 1, 2, 3, 4);
303 c.emplace(c.cbegin(), 1, 2, 3);
304 c.emplace(c.cbegin(), 1, 2);
305 c.emplace(c.cbegin(), 1);
306 c.emplace(c.cbegin());
307 if(!test_expected_container(c, &expected[0], 6)){
308 return false;
309 }
310 c.clear();
311 //emplace_back-like
312 typename Container::const_iterator i = c.emplace(c.cend());
313 if(!test_expected_container(c, &expected[0], 1)){
314 return false;
315 }
316 i = c.emplace(++i, 1);
317 if(!test_expected_container(c, &expected[0], 2)){
318 return false;
319 }
320 i = c.emplace(++i, 1, 2);
321 if(!test_expected_container(c, &expected[0], 3)){
322 return false;
323 }
324 i = c.emplace(++i, 1, 2, 3);
325 if(!test_expected_container(c, &expected[0], 4)){
326 return false;
327 }
328 i = c.emplace(++i, 1, 2, 3, 4);
329 if(!test_expected_container(c, &expected[0], 5)){
330 return false;
331 }
332 i = c.emplace(++i, 1, 2, 3, 4, 5);
333 if(!test_expected_container(c, &expected[0], 6)){
334 return false;
335 }
336 c.clear();
337 //emplace in the middle
338 c.emplace(c.cbegin());
339 if(!test_expected_container(c, &expected[0], 1)){
340 return false;
341 }
342 i = c.emplace(c.cend(), 1, 2, 3, 4, 5);
343 if(!test_expected_container(c, &expected[0], 1)){
344 return false;
345 }
346 if(!test_expected_container(c, &expected[5], 1, 1)){
347 return false;
348 }
349 i = c.emplace(i, 1, 2, 3, 4);
350 if(!test_expected_container(c, &expected[0], 1)){
351 return false;
352 }
353 if(!test_expected_container(c, &expected[4], 2, 1)){
354 return false;
355 }
356 i = c.emplace(i, 1, 2, 3);
357 if(!test_expected_container(c, &expected[0], 1)){
358 return false;
359 }
360 if(!test_expected_container(c, &expected[3], 3, 1)){
361 return false;
362 }
363 i = c.emplace(i, 1, 2);
364 if(!test_expected_container(c, &expected[0], 1)){
365 return false;
366 }
367 if(!test_expected_container(c, &expected[2], 4, 1)){
368 return false;
369 }
370 i = c.emplace(i, 1);
371 if(!test_expected_container(c, &expected[0], 6)){
372 return false;
373 }
374 std::cout << "...OK" << std::endl;
375 }
376 return true;
377}
378
379template<class Container>
380bool test_emplace_before(dtl::false_)
381{ return true; }
382
383template<class Container>
384bool test_emplace_after(dtl::true_)
385{
386 std::cout << "Starting test_emplace_after." << std::endl << " Class: "
387 << typeid(Container).name() << std::endl;
388 static EmplaceInt expected [10];
389 {
390 new(&expected [0]) EmplaceInt();
391 new(&expected [1]) EmplaceInt(1);
392 new(&expected [2]) EmplaceInt();
393 Container c;
394 typename Container::const_iterator i = c.emplace_after(c.cbefore_begin(), 1);
395 c.emplace_after(c.cbefore_begin());
396 if(!test_expected_container(c, &expected[0], 2)){
397 return false;
398 }
399 c.emplace_after(i);
400 if(!test_expected_container(c, &expected[0], 3)){
401 return false;
402 }
403 }
404 {
405 new(&expected [0]) EmplaceInt();
406 new(&expected [1]) EmplaceInt(1);
407 new(&expected [2]) EmplaceInt(1, 2);
408 new(&expected [3]) EmplaceInt(1, 2, 3);
409 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
410 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
411 //emplace_front-like
412 Container c;
413 c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4, 5);
414 c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4);
415 c.emplace_after(c.cbefore_begin(), 1, 2, 3);
416 c.emplace_after(c.cbefore_begin(), 1, 2);
417 c.emplace_after(c.cbefore_begin(), 1);
418 c.emplace_after(c.cbefore_begin());
419 if(!test_expected_container(c, &expected[0], 6)){
420 return false;
421 }
422 c.clear();
423 //emplace_back-like
424 typename Container::const_iterator i = c.emplace_after(c.cbefore_begin());
425 if(!test_expected_container(c, &expected[0], 1)){
426 return false;
427 }
428 i = c.emplace_after(i, 1);
429 if(!test_expected_container(c, &expected[0], 2)){
430 return false;
431 }
432 i = c.emplace_after(i, 1, 2);
433 if(!test_expected_container(c, &expected[0], 3)){
434 return false;
435 }
436 i = c.emplace_after(i, 1, 2, 3);
437 if(!test_expected_container(c, &expected[0], 4)){
438 return false;
439 }
440 i = c.emplace_after(i, 1, 2, 3, 4);
441 if(!test_expected_container(c, &expected[0], 5)){
442 return false;
443 }
444 i = c.emplace_after(i, 1, 2, 3, 4, 5);
445 if(!test_expected_container(c, &expected[0], 6)){
446 return false;
447 }
448 c.clear();
449 //emplace_after in the middle
450 i = c.emplace_after(c.cbefore_begin());
451 c.emplace_after(i, 1, 2, 3, 4, 5);
452 c.emplace_after(i, 1, 2, 3, 4);
453 c.emplace_after(i, 1, 2, 3);
454 c.emplace_after(i, 1, 2);
455 c.emplace_after(i, 1);
456
457 if(!test_expected_container(c, &expected[0], 6)){
458 return false;
459 }
460 std::cout << "...OK" << std::endl;
461 }
462 return true;
463}
464
465template<class Container>
466bool test_emplace_after(dtl::false_)
467{ return true; }
468
469template<class Container>
470bool test_emplace_assoc(dtl::true_)
471{
472 std::cout << "Starting test_emplace_assoc." << std::endl << " Class: "
473 << typeid(Container).name() << std::endl;
474 static EmplaceInt expected [10];
475 new(&expected [0]) EmplaceInt();
476 new(&expected [1]) EmplaceInt(1);
477 new(&expected [2]) EmplaceInt(1, 2);
478 new(&expected [3]) EmplaceInt(1, 2, 3);
479 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
480 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
481 {
482 Container c;
483 c.emplace();
484 if(!test_expected_container(c, &expected[0], 1)){
485 return false;
486 }
487 c.emplace(1);
488 if(!test_expected_container(c, &expected[0], 2)){
489 return false;
490 }
491 c.emplace(1, 2);
492 if(!test_expected_container(c, &expected[0], 3)){
493 return false;
494 }
495 c.emplace(1, 2, 3);
496 if(!test_expected_container(c, &expected[0], 4)){
497 return false;
498 }
499 c.emplace(1, 2, 3, 4);
500 if(!test_expected_container(c, &expected[0], 5)){
501 return false;
502 }
503 c.emplace(1, 2, 3, 4, 5);
504 if(!test_expected_container(c, &expected[0], 6)){
505 return false;
506 }
507 std::cout << "...OK" << std::endl;
508 }
509 return true;
510}
511
512template<class Container>
513bool test_emplace_assoc(dtl::false_)
514{ return true; }
515
516template<class Container>
517bool test_emplace_hint(dtl::true_)
518{
519 std::cout << "Starting test_emplace_hint." << std::endl << " Class: "
520 << typeid(Container).name() << std::endl;
521 static EmplaceInt expected [10];
522 new(&expected [0]) EmplaceInt();
523 new(&expected [1]) EmplaceInt(1);
524 new(&expected [2]) EmplaceInt(1, 2);
525 new(&expected [3]) EmplaceInt(1, 2, 3);
526 new(&expected [4]) EmplaceInt(1, 2, 3, 4);
527 new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
528
529 {
530 Container c;
531 typename Container::const_iterator it;
532 it = c.emplace_hint(c.begin());
533 if(!test_expected_container(c, &expected[0], 1)){
534 return false;
535 }
536 it = c.emplace_hint(it, 1);
537 if(!test_expected_container(c, &expected[0], 2)){
538 return false;
539 }
540 it = c.emplace_hint(it, 1, 2);
541 if(!test_expected_container(c, &expected[0], 3)){
542 return false;
543 }
544 it = c.emplace_hint(it, 1, 2, 3);
545 if(!test_expected_container(c, &expected[0], 4)){
546 return false;
547 }
548 it = c.emplace_hint(it, 1, 2, 3, 4);
549 if(!test_expected_container(c, &expected[0], 5)){
550 return false;
551 }
552 it = c.emplace_hint(it, 1, 2, 3, 4, 5);
553 if(!test_expected_container(c, &expected[0], 6)){
554 return false;
555 }
556 std::cout << "...OK" << std::endl;
557 }
558
559 return true;
560}
561
562template<class Container>
563bool test_emplace_hint(dtl::false_)
564{ return true; }
565
566template<class Container>
567bool test_emplace_assoc_pair(dtl::true_)
568{
569 std::cout << "Starting test_emplace_assoc_pair." << std::endl << " Class: "
570 << typeid(Container).name() << std::endl;
571
572 new(&expected_pair[0].first) EmplaceInt();
573 new(&expected_pair[0].second) EmplaceInt();
574 new(&expected_pair[1].first) EmplaceInt(1);
575 new(&expected_pair[1].second) EmplaceInt(1);
576 new(&expected_pair[2].first) EmplaceInt(2);
577 new(&expected_pair[2].second) EmplaceInt(2);
578 {
579 Container c;
580 c.emplace();
581 if(!test_expected_container(c, &expected_pair[0], 1)){
582 std::cout << "Error after c.emplace();\n";
583 return false;
584 }
585 c.emplace(1, 1);
586 if(!test_expected_container(c, &expected_pair[0], 2)){
587 std::cout << "Error after c.emplace(1);\n";
588 return false;
589 }
590 c.emplace(2, 2);
591 if(!test_expected_container(c, &expected_pair[0], 3)){
592 std::cout << "Error after c.emplace(2, 2);\n";
593 return false;
594 }
595 std::cout << "...OK" << std::endl;
596 }
597 return true;
598}
599
600template<class Container>
601bool test_emplace_assoc_pair(dtl::false_)
602{ return true; }
603
604template<class Container>
605bool test_emplace_hint_pair(dtl::true_)
606{
607 std::cout << "Starting test_emplace_hint_pair." << std::endl << " Class: "
608 << typeid(Container).name() << std::endl;
609
610 new(&expected_pair[0].first) EmplaceInt();
611 new(&expected_pair[0].second) EmplaceInt();
612 new(&expected_pair[1].first) EmplaceInt(1);
613 new(&expected_pair[1].second) EmplaceInt(1);
614 new(&expected_pair[2].first) EmplaceInt(2);
615 new(&expected_pair[2].second) EmplaceInt(2);
616 {
617 Container c;
618 typename Container::const_iterator it;
619 it = c.emplace_hint(c.begin());
620 if(!test_expected_container(c, &expected_pair[0], 1)){
621 std::cout << "Error after c.emplace(1);\n";
622 return false;
623 }
624 it = c.emplace_hint(it, 1, 1);
625 if(!test_expected_container(c, &expected_pair[0], 2)){
626 std::cout << "Error after c.emplace(it, 1);\n";
627 return false;
628 }
629 it = c.emplace_hint(it, 2, 2);
630 if(!test_expected_container(c, &expected_pair[0], 3)){
631 std::cout << "Error after c.emplace(it, 2, 2);\n";
632 return false;
633 }
634 std::cout << "...OK" << std::endl;
635 }
636 return true;
637}
638
639template<class Container>
640bool test_emplace_hint_pair(dtl::false_)
641{ return true; }
642
643template <EmplaceOptions O, EmplaceOptions Mask>
644struct emplace_active
645{
646 static const bool value = (0 != (O & Mask));
647 typedef dtl::bool_<value> type;
648 operator type() const{ return type(); }
649};
650
651template<class Container, EmplaceOptions O>
652bool test_emplace()
653{
654 if(!test_emplace_back<Container>(emplace_active<O, EMPLACE_BACK>())){
655 return false;
656 }
657 if(!test_emplace_front<Container>(emplace_active<O, EMPLACE_FRONT>())){
658 return false;
659 }
660 if(!test_emplace_before<Container>(emplace_active<O, EMPLACE_BEFORE>())){
661 return false;
662 }
663 if(!test_emplace_after<Container>(emplace_active<O, EMPLACE_AFTER>())){
664 return false;
665 }
666 if(!test_emplace_assoc<Container>(emplace_active<O, EMPLACE_ASSOC>())){
667 return false;
668 }
669 if(!test_emplace_hint<Container>(emplace_active<O, EMPLACE_HINT>())){
670 return false;
671 }
672 if(!test_emplace_assoc_pair<Container>(emplace_active<O, EMPLACE_ASSOC_PAIR>())){
673 return false;
674 }
675 if(!test_emplace_hint_pair<Container>(emplace_active<O, EMPLACE_HINT_PAIR>())){
676 return false;
677 }
678 return true;
679}
680
681} //namespace test{
682} //namespace container {
683} //namespace boost{
684
685#include <boost/container/detail/config_end.hpp>
686
687#endif //#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
688

source code of boost/libs/container/test/emplace_test.hpp