1 // (C) Copyright Dave Abrahams and Thomas Becker 2003. Distributed
2 // under the Boost Software License, Version 1.0. (See accompanying
3 // file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 //
6 
7 // File:
8 // =====
9 // zip_iterator_test_main.cpp
10 
11 // Author:
12 // =======
13 // Thomas Becker
14 
15 // Created:
16 // ========
17 // Jul 15, 2003
18 
19 // Purpose:
20 // ========
21 // Test driver for zip_iterator.hpp
22 
23 // Compilers Tested:
24 // =================
25 // Metrowerks Codewarrior Pro 7.2, 8.3
26 // gcc 2.95.3
27 // gcc 3.2
28 // Microsoft VC 6sp5 (test fails due to some compiler bug)
29 // Microsoft VC 7 (works)
30 // Microsoft VC 7.1
31 // Intel 5
32 // Intel 6
33 // Intel 7.1
34 // Intel 8
35 // Borland 5.5.1 (broken due to lack of support from Boost.Tuples)
36 
37 /////////////////////////////////////////////////////////////////////////////
38 //
39 // Includes
40 //
41 /////////////////////////////////////////////////////////////////////////////
42 
43 #include <boost/iterator/zip_iterator.hpp>
44 #include <boost/iterator/zip_iterator.hpp> // 2nd #include tests #include guard.
45 #include <iostream>
46 #include <vector>
47 #include <list>
48 #include <set>
49 #include <string>
50 #include <functional>
51 #include <boost/tuple/tuple.hpp>
52 #include <boost/iterator/transform_iterator.hpp>
53 #include <boost/iterator/is_readable_iterator.hpp>
54 #include <boost/type_traits/is_same.hpp>
55 #include <boost/detail/workaround.hpp>
56 #include <stddef.h>
57 
58 
59 /// Tests for https://svn.boost.org/trac/boost/ticket/1517
to_value(int const & v)60 int to_value(int const &v)
61 {
62     return v;
63 }
64 
category_test()65 void category_test()
66 {
67     std::list<int> rng1;
68     std::string rng2;
69 
70     boost::make_zip_iterator(
71         boost::make_tuple(
72             boost::make_transform_iterator(rng1.begin(), &to_value), // BidirectionalInput
73             rng2.begin() // RandomAccess
74         )
75     );
76 }
77 ///
78 
79 /////////////////////////////////////////////////////////////////////////////
80 //
81 // Das Main Funktion
82 //
83 /////////////////////////////////////////////////////////////////////////////
84 
main(void)85 int main( void )
86 {
87 
88   category_test();
89 
90   std::cout << "\n"
91             << "***********************************************\n"
92             << "*                                             *\n"
93             << "* Test driver for boost::zip_iterator         *\n"
94             << "* Copyright Thomas Becker 2003                *\n"
95             << "*                                             *\n"
96             << "***********************************************\n\n"
97             << std::flush;
98 
99   size_t num_successful_tests = 0;
100   size_t num_failed_tests = 0;
101 
102   /////////////////////////////////////////////////////////////////////////////
103   //
104   // Zip iterator construction and dereferencing
105   //
106   /////////////////////////////////////////////////////////////////////////////
107 
108   std::cout << "Zip iterator construction and dereferencing: "
109             << std::flush;
110 
111   std::vector<double> vect1(3);
112   vect1[0] = 42.;
113   vect1[1] = 43.;
114   vect1[2] = 44.;
115 
116   std::set<int> intset;
117   intset.insert(52);
118   intset.insert(53);
119   intset.insert(54);
120   //
121 
122   typedef
123   boost::zip_iterator<
124       boost::tuples::tuple<
125           std::set<int>::iterator
126         , std::vector<double>::iterator
127       >
128   > zit_mixed;
129 
130   zit_mixed zip_it_mixed = zit_mixed(
131     boost::make_tuple(
132         intset.begin()
133       , vect1.begin()
134     )
135   );
136 
137   boost::tuples::tuple<int, double> val_tuple(
138       *zip_it_mixed);
139 
140   boost::tuples::tuple<const int&, double&> ref_tuple(
141       *zip_it_mixed);
142 
143   double dblOldVal = boost::tuples::get<1>(ref_tuple);
144   boost::tuples::get<1>(ref_tuple) -= 41.;
145 
146   if( 52 == boost::tuples::get<0>(val_tuple) &&
147       42. == boost::tuples::get<1>(val_tuple) &&
148       52 == boost::tuples::get<0>(ref_tuple)  &&
149       1. == boost::tuples::get<1>(ref_tuple)  &&
150       1. == *vect1.begin()
151     )
152   {
153     ++num_successful_tests;
154     std::cout << "OK" << std::endl;
155   }
156   else
157   {
158     ++num_failed_tests = 0;
159     std::cout << "not OK" << std::endl;
160   }
161 
162   // Undo change to vect1
163   boost::tuples::get<1>(ref_tuple) = dblOldVal;
164 
165   /////////////////////////////////////////////////////////////////////////////
166   //
167   // Zip iterator with 12 components
168   //
169   /////////////////////////////////////////////////////////////////////////////
170 
171   std::cout << "Zip iterators with 12 components:            "
172             << std::flush;
173 
174   // Declare 12 containers
175   //
176   std::list<int> li1;
177   li1.push_back(1);
178   std::set<int> se1;
179   se1.insert(2);
180   std::vector<int> ve1;
181   ve1.push_back(3);
182   //
183   std::list<int> li2;
184   li2.push_back(4);
185   std::set<int> se2;
186   se2.insert(5);
187   std::vector<int> ve2;
188   ve2.push_back(6);
189   //
190   std::list<int> li3;
191   li3.push_back(7);
192   std::set<int> se3;
193   se3.insert(8);
194   std::vector<int> ve3;
195   ve3.push_back(9);
196   //
197   std::list<int> li4;
198   li4.push_back(10);
199   std::set<int> se4;
200   se4.insert(11);
201   std::vector<int> ve4;
202   ve4.push_back(12);
203 
204   // typedefs for cons lists of iterators.
205   typedef boost::tuples::cons<
206     std::set<int>::iterator,
207     boost::tuples::tuple<
208       std::vector<int>::iterator,
209       std::list<int>::iterator,
210       std::set<int>::iterator,
211       std::vector<int>::iterator,
212       std::list<int>::iterator,
213       std::set<int>::iterator,
214       std::vector<int>::iterator,
215       std::list<int>::iterator,
216       std::set<int>::iterator,
217       std::vector<int>::const_iterator
218       >::inherited
219     > cons_11_its_type;
220   //
221   typedef boost::tuples::cons<
222     std::list<int>::const_iterator,
223     cons_11_its_type
224     > cons_12_its_type;
225 
226   // typedefs for cons lists for dereferencing the zip iterator
227   // made from the cons list above.
228   typedef boost::tuples::cons<
229     const int&,
230     boost::tuples::tuple<
231       int&,
232       int&,
233       const int&,
234       int&,
235       int&,
236       const int&,
237       int&,
238       int&,
239       const int&,
240       const int&
241       >::inherited
242     > cons_11_refs_type;
243   //
244   typedef boost::tuples::cons<
245     const int&,
246     cons_11_refs_type
247     > cons_12_refs_type;
248 
249   // typedef for zip iterator with 12 elements
250   typedef boost::zip_iterator<cons_12_its_type> zip_it_12_type;
251 
252   // Declare a 12-element zip iterator.
253   zip_it_12_type zip_it_12(
254     cons_12_its_type(
255       li1.begin(),
256       cons_11_its_type(
257         se1.begin(),
258         boost::make_tuple(
259           ve1.begin(),
260           li2.begin(),
261           se2.begin(),
262           ve2.begin(),
263           li3.begin(),
264           se3.begin(),
265           ve3.begin(),
266           li4.begin(),
267           se4.begin(),
268           ve4.begin()
269           )
270         )
271       )
272     );
273 
274   // Dereference, mess with the result a little.
275   cons_12_refs_type zip_it_12_dereferenced(*zip_it_12);
276   boost::tuples::get<9>(zip_it_12_dereferenced) = 42;
277 
278   // Make a copy and move it a little to force some instantiations.
279   zip_it_12_type zip_it_12_copy(zip_it_12);
280   ++zip_it_12_copy;
281 
282   if( boost::tuples::get<11>(zip_it_12.get_iterator_tuple()) == ve4.begin() &&
283       boost::tuples::get<11>(zip_it_12_copy.get_iterator_tuple()) == ve4.end() &&
284       1 == boost::tuples::get<0>(zip_it_12_dereferenced) &&
285       12 == boost::tuples::get<11>(zip_it_12_dereferenced) &&
286       42 == *(li4.begin())
287     )
288   {
289     ++num_successful_tests;
290     std::cout << "OK" << std::endl;
291   }
292   else
293   {
294     ++num_failed_tests = 0;
295     std::cout << "not OK" << std::endl;
296   }
297 
298   /////////////////////////////////////////////////////////////////////////////
299   //
300   // Zip iterator incrementing and dereferencing
301   //
302   /////////////////////////////////////////////////////////////////////////////
303 
304   std::cout << "Zip iterator ++ and *:                       "
305             << std::flush;
306 
307   std::vector<double> vect2(3);
308   vect2[0] = 2.2;
309   vect2[1] = 3.3;
310   vect2[2] = 4.4;
311 
312   boost::zip_iterator<
313     boost::tuples::tuple<
314       std::vector<double>::const_iterator,
315       std::vector<double>::const_iterator
316       >
317     >
318   zip_it_begin(
319     boost::make_tuple(
320      vect1.begin(),
321      vect2.begin()
322      )
323   );
324 
325   boost::zip_iterator<
326     boost::tuples::tuple<
327       std::vector<double>::const_iterator,
328       std::vector<double>::const_iterator
329       >
330     >
331   zip_it_run(
332     boost::make_tuple(
333      vect1.begin(),
334      vect2.begin()
335      )
336   );
337 
338   boost::zip_iterator<
339     boost::tuples::tuple<
340       std::vector<double>::const_iterator,
341       std::vector<double>::const_iterator
342       >
343     >
344   zip_it_end(
345     boost::make_tuple(
346      vect1.end(),
347      vect2.end()
348      )
349   );
350 
351   if( zip_it_run == zip_it_begin &&
352       42. == boost::tuples::get<0>(*zip_it_run) &&
353       2.2 == boost::tuples::get<1>(*zip_it_run) &&
354       43. == boost::tuples::get<0>(*(++zip_it_run)) &&
355       3.3 == boost::tuples::get<1>(*zip_it_run) &&
356       44. == boost::tuples::get<0>(*(++zip_it_run)) &&
357       4.4 == boost::tuples::get<1>(*zip_it_run) &&
358       zip_it_end == ++zip_it_run
359     )
360   {
361     ++num_successful_tests;
362     std::cout << "OK" << std::endl;
363   }
364   else
365   {
366     ++num_failed_tests = 0;
367     std::cout << "not OK" << std::endl;
368   }
369 
370   /////////////////////////////////////////////////////////////////////////////
371   //
372   // Zip iterator decrementing and dereferencing
373   //
374   /////////////////////////////////////////////////////////////////////////////
375 
376   std::cout << "Zip iterator -- and *:                       "
377             << std::flush;
378 
379   if( zip_it_run == zip_it_end &&
380       zip_it_end == zip_it_run-- &&
381       44. == boost::tuples::get<0>(*zip_it_run) &&
382       4.4 == boost::tuples::get<1>(*zip_it_run) &&
383       43. == boost::tuples::get<0>(*(--zip_it_run)) &&
384       3.3 == boost::tuples::get<1>(*zip_it_run) &&
385       42. == boost::tuples::get<0>(*(--zip_it_run)) &&
386       2.2 == boost::tuples::get<1>(*zip_it_run) &&
387       zip_it_begin == zip_it_run
388     )
389   {
390     ++num_successful_tests;
391     std::cout << "OK" << std::endl;
392   }
393   else
394   {
395     ++num_failed_tests = 0;
396     std::cout << "not OK" << std::endl;
397   }
398 
399   /////////////////////////////////////////////////////////////////////////////
400   //
401   // Zip iterator copy construction and equality
402   //
403   /////////////////////////////////////////////////////////////////////////////
404 
405   std::cout << "Zip iterator copy construction and equality: "
406             << std::flush;
407 
408   boost::zip_iterator<
409     boost::tuples::tuple<
410       std::vector<double>::const_iterator,
411       std::vector<double>::const_iterator
412       >
413     > zip_it_run_copy(zip_it_run);
414 
415   if(zip_it_run == zip_it_run && zip_it_run == zip_it_run_copy)
416   {
417     ++num_successful_tests;
418     std::cout << "OK" << std::endl;
419   }
420   else
421   {
422     ++num_failed_tests = 0;
423     std::cout << "not OK" << std::endl;
424   }
425 
426   /////////////////////////////////////////////////////////////////////////////
427   //
428   // Zip iterator inequality
429   //
430   /////////////////////////////////////////////////////////////////////////////
431 
432   std::cout << "Zip iterator inequality:                     "
433             << std::flush;
434 
435   if(!(zip_it_run != zip_it_run_copy) && zip_it_run != ++zip_it_run_copy)
436   {
437     ++num_successful_tests;
438     std::cout << "OK" << std::endl;
439   }
440   else
441   {
442     ++num_failed_tests = 0;
443     std::cout << "not OK" << std::endl;
444   }
445 
446   /////////////////////////////////////////////////////////////////////////////
447   //
448   // Zip iterator less than
449   //
450   /////////////////////////////////////////////////////////////////////////////
451 
452   std::cout << "Zip iterator less than:                      "
453             << std::flush;
454 
455   // Note: zip_it_run_copy == zip_it_run + 1
456   //
457   if( zip_it_run < zip_it_run_copy  &&
458       !( zip_it_run < --zip_it_run_copy) &&
459       zip_it_run == zip_it_run_copy
460     )
461   {
462     ++num_successful_tests;
463     std::cout << "OK" << std::endl;
464   }
465   else
466   {
467     ++num_failed_tests = 0;
468     std::cout << "not OK" << std::endl;
469   }
470 
471   /////////////////////////////////////////////////////////////////////////////
472   //
473   // Zip iterator less than or equal
474   //
475   /////////////////////////////////////////////////////////////////////////////
476 
477   std::cout << "zip iterator less than or equal:             "
478             << std::flush;
479 
480   // Note: zip_it_run_copy == zip_it_run
481   //
482   ++zip_it_run;
483   zip_it_run_copy += 2;
484 
485   if( zip_it_run <= zip_it_run_copy &&
486       zip_it_run <= --zip_it_run_copy &&
487       !( zip_it_run <= --zip_it_run_copy) &&
488       zip_it_run <= zip_it_run
489     )
490   {
491     ++num_successful_tests;
492     std::cout << "OK" << std::endl;
493   }
494   else
495   {
496     ++num_failed_tests = 0;
497     std::cout << "not OK" << std::endl;
498   }
499 
500   /////////////////////////////////////////////////////////////////////////////
501   //
502   // Zip iterator greater than
503   //
504   /////////////////////////////////////////////////////////////////////////////
505 
506   std::cout << "Zip iterator greater than:                   "
507             << std::flush;
508 
509   // Note: zip_it_run_copy == zip_it_run - 1
510   //
511   if( zip_it_run > zip_it_run_copy &&
512       !( zip_it_run > ++zip_it_run_copy) &&
513       zip_it_run == zip_it_run_copy
514     )
515   {
516     ++num_successful_tests;
517     std::cout << "OK" << std::endl;
518   }
519   else
520   {
521     ++num_failed_tests = 0;
522     std::cout << "not OK" << std::endl;
523   }
524 
525   /////////////////////////////////////////////////////////////////////////////
526   //
527   // Zip iterator greater than or equal
528   //
529   /////////////////////////////////////////////////////////////////////////////
530 
531   std::cout << "Zip iterator greater than or equal:          "
532             << std::flush;
533 
534   ++zip_it_run;
535 
536   // Note: zip_it_run == zip_it_run_copy + 1
537   //
538   if( zip_it_run >= zip_it_run_copy &&
539       --zip_it_run >= zip_it_run_copy &&
540       ! (zip_it_run >= ++zip_it_run_copy)
541     )
542   {
543     ++num_successful_tests;
544     std::cout << "OK" << std::endl;
545   }
546   else
547   {
548     ++num_failed_tests = 0;
549     std::cout << "not OK" << std::endl;
550   }
551 
552   /////////////////////////////////////////////////////////////////////////////
553   //
554   // Zip iterator + int
555   //
556   /////////////////////////////////////////////////////////////////////////////
557 
558   std::cout << "Zip iterator + int:                          "
559             << std::flush;
560 
561   // Note: zip_it_run == zip_it_run_copy - 1
562   //
563   zip_it_run = zip_it_run + 2;
564   ++zip_it_run_copy;
565 
566   if( zip_it_run == zip_it_run_copy && zip_it_run == zip_it_begin + 3 )
567   {
568     ++num_successful_tests;
569     std::cout << "OK" << std::endl;
570   }
571   else
572   {
573     ++num_failed_tests = 0;
574     std::cout << "not OK" << std::endl;
575   }
576 
577   /////////////////////////////////////////////////////////////////////////////
578   //
579   // Zip iterator - int
580   //
581   /////////////////////////////////////////////////////////////////////////////
582 
583   std::cout << "Zip iterator - int:                          "
584             << std::flush;
585 
586   // Note: zip_it_run == zip_it_run_copy, and both are at end position
587   //
588   zip_it_run = zip_it_run - 2;
589   --zip_it_run_copy;
590   --zip_it_run_copy;
591 
592   if( zip_it_run == zip_it_run_copy && (zip_it_run - 1) == zip_it_begin )
593   {
594     ++num_successful_tests;
595     std::cout << "OK" << std::endl;
596   }
597   else
598   {
599     ++num_failed_tests = 0;
600     std::cout << "not OK" << std::endl;
601   }
602 
603   /////////////////////////////////////////////////////////////////////////////
604   //
605   // Zip iterator +=
606   //
607   /////////////////////////////////////////////////////////////////////////////
608 
609   std::cout << "Zip iterator +=:                             "
610             << std::flush;
611 
612   // Note: zip_it_run == zip_it_run_copy, and both are at begin + 1
613   //
614   zip_it_run += 2;
615   if( zip_it_run == zip_it_begin + 3 )
616   {
617     ++num_successful_tests;
618     std::cout << "OK" << std::endl;
619   }
620   else
621   {
622     ++num_failed_tests = 0;
623     std::cout << "not OK" << std::endl;
624   }
625 
626   /////////////////////////////////////////////////////////////////////////////
627   //
628   // Zip iterator -=
629   //
630   /////////////////////////////////////////////////////////////////////////////
631 
632   std::cout << "Zip iterator -=:                             "
633             << std::flush;
634 
635   // Note: zip_it_run is at end position, zip_it_run_copy is at
636   // begin plus one.
637   //
638   zip_it_run -= 2;
639   if( zip_it_run == zip_it_run_copy )
640   {
641     ++num_successful_tests;
642     std::cout << "OK" << std::endl;
643   }
644   else
645   {
646     ++num_failed_tests = 0;
647     std::cout << "not OK" << std::endl;
648   }
649 
650   /////////////////////////////////////////////////////////////////////////////
651   //
652   // Zip iterator getting member iterators
653   //
654   /////////////////////////////////////////////////////////////////////////////
655 
656   std::cout << "Zip iterator member iterators:               "
657             << std::flush;
658 
659   // Note: zip_it_run and zip_it_run_copy are both at
660   // begin plus one.
661   //
662   if( boost::tuples::get<0>(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 &&
663       boost::tuples::get<1>(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1
664     )
665   {
666     ++num_successful_tests;
667     std::cout << "OK" << std::endl;
668   }
669   else
670   {
671     ++num_failed_tests = 0;
672     std::cout << "not OK" << std::endl;
673   }
674 
675   /////////////////////////////////////////////////////////////////////////////
676   //
677   // Making zip iterators
678   //
679   /////////////////////////////////////////////////////////////////////////////
680 
681   std::cout << "Making zip iterators:                        "
682             << std::flush;
683 
684   std::vector<boost::tuples::tuple<double, double> >
685     vect_of_tuples(3);
686 
687   std::copy(
688     boost::make_zip_iterator(
689     boost::make_tuple(
690       vect1.begin(),
691       vect2.begin()
692       )
693     ),
694     boost::make_zip_iterator(
695     boost::make_tuple(
696       vect1.end(),
697       vect2.end()
698       )
699     ),
700     vect_of_tuples.begin()
701   );
702 
703   if( 42. == boost::tuples::get<0>(*vect_of_tuples.begin()) &&
704       2.2 == boost::tuples::get<1>(*vect_of_tuples.begin()) &&
705       43. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 1)) &&
706       3.3 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 1)) &&
707       44. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 2)) &&
708       4.4 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 2))
709     )
710   {
711     ++num_successful_tests;
712     std::cout << "OK" << std::endl;
713   }
714   else
715   {
716     ++num_failed_tests = 0;
717     std::cout << "not OK" << std::endl;
718   }
719 
720   /////////////////////////////////////////////////////////////////////////////
721   //
722   // Zip iterator non-const --> const conversion
723   //
724   /////////////////////////////////////////////////////////////////////////////
725 
726   std::cout << "Zip iterator non-const to const conversion:  "
727             << std::flush;
728 
729   boost::zip_iterator<
730     boost::tuples::tuple<
731       std::set<int>::const_iterator,
732       std::vector<double>::const_iterator
733       >
734     >
735   zip_it_const(
736     boost::make_tuple(
737       intset.begin(),
738       vect2.begin()
739     )
740   );
741   //
742   boost::zip_iterator<
743     boost::tuples::tuple<
744       std::set<int>::iterator,
745       std::vector<double>::const_iterator
746       >
747     >
748   zip_it_half_const(
749     boost::make_tuple(
750       intset.begin(),
751       vect2.begin()
752     )
753   );
754   //
755   boost::zip_iterator<
756     boost::tuples::tuple<
757       std::set<int>::iterator,
758       std::vector<double>::iterator
759       >
760     >
761   zip_it_non_const(
762     boost::make_tuple(
763       intset.begin(),
764       vect2.begin()
765     )
766   );
767 
768   zip_it_half_const = ++zip_it_non_const;
769   zip_it_const = zip_it_half_const;
770   ++zip_it_const;
771 //  zip_it_non_const = ++zip_it_const;  // Error: can't convert from const to non-const
772 
773   if( 54 == boost::tuples::get<0>(*zip_it_const) &&
774       4.4 == boost::tuples::get<1>(*zip_it_const)  &&
775       53 == boost::tuples::get<0>(*zip_it_half_const)  &&
776       3.3 == boost::tuples::get<1>(*zip_it_half_const)
777     )
778   {
779     ++num_successful_tests;
780     std::cout << "OK" << std::endl;
781   }
782   else
783   {
784     ++num_failed_tests = 0;
785     std::cout << "not OK" << std::endl;
786   }
787 
788 
789   /////////////////////////////////////////////////////////////////////////////
790   //
791   // Zip iterator categories
792   //
793   /////////////////////////////////////////////////////////////////////////////
794 
795   std::cout << "Zip iterator categories:                     "
796             << std::flush;
797 
798   // The big iterator of the previous test has vector, list, and set iterators.
799   // Therefore, it must be bidirectional, but not random access.
800   bool bBigItIsBidirectionalIterator = boost::is_convertible<
801     boost::iterator_traversal<zip_it_12_type>::type
802         , boost::bidirectional_traversal_tag
803         >::value;
804 
805   bool bBigItIsRandomAccessIterator = boost::is_convertible<
806     boost::iterator_traversal<zip_it_12_type>::type
807         , boost::random_access_traversal_tag
808         >::value;
809 
810   // A combining iterator with all vector iterators must have random access
811   // traversal.
812   //
813   typedef boost::zip_iterator<
814     boost::tuples::tuple<
815       std::vector<double>::const_iterator,
816       std::vector<double>::const_iterator
817       >
818     > all_vects_type;
819 
820   bool bAllVectsIsRandomAccessIterator = boost::is_convertible<
821     boost::iterator_traversal<all_vects_type>::type
822         , boost::random_access_traversal_tag
823     >::value;
824 
825   // The big test.
826   if( bBigItIsBidirectionalIterator &&
827       ! bBigItIsRandomAccessIterator &&
828       bAllVectsIsRandomAccessIterator
829     )
830   {
831     ++num_successful_tests;
832     std::cout << "OK" << std::endl;
833   }
834   else
835   {
836     ++num_failed_tests = 0;
837     std::cout << "not OK" << std::endl;
838   }
839 
840   // Done
841   //
842   std::cout << "\nTest Result:"
843             << "\n============"
844             << "\nNumber of successful tests: " << static_cast<unsigned int>(num_successful_tests)
845             << "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests)
846             << std::endl;
847 
848   return num_failed_tests;
849 }
850 
851