blob: c6692d21b0dc64c950bd3e7f035e8f84517d9b39 [file] [log] [blame]
// (C) Copyright Dave Abrahams and Thomas Becker 2003. Distributed
// under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// File:
// =====
// zip_iterator_test_main.cpp
// Author:
// =======
// Thomas Becker
// Created:
// ========
// Jul 15, 2003
// Purpose:
// ========
// Test driver for zip_iterator.hpp
// Compilers Tested:
// =================
// Metrowerks Codewarrior Pro 7.2, 8.3
// gcc 2.95.3
// gcc 3.2
// Microsoft VC 6sp5 (test fails due to some compiler bug)
// Microsoft VC 7 (works)
// Microsoft VC 7.1
// Intel 5
// Intel 6
// Intel 7.1
// Intel 8
// Borland 5.5.1 (broken due to lack of support from Boost.Tuples)
/////////////////////////////////////////////////////////////////////////////
//
// Includes
//
/////////////////////////////////////////////////////////////////////////////
#include <boost/iterator/zip_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp> // 2nd #include tests #include guard.
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <functional>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/is_readable_iterator.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/detail/workaround.hpp>
#include <stddef.h>
template <class It>
struct pure_traversal
: boost::detail::pure_traversal_tag<
typename boost::iterator_traversal<It>::type
>
{};
/////////////////////////////////////////////////////////////////////////////
//
// Das Main Funktion
//
/////////////////////////////////////////////////////////////////////////////
int main( void )
{
std::cout << "\n"
<< "***********************************************\n"
<< "* *\n"
<< "* Test driver for boost::zip_iterator *\n"
<< "* Copyright Thomas Becker 2003 *\n"
<< "* *\n"
<< "***********************************************\n\n"
<< std::flush;
size_t num_successful_tests = 0;
size_t num_failed_tests = 0;
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator construction and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator construction and dereferencing: "
<< std::flush;
std::vector<double> vect1(3);
vect1[0] = 42.;
vect1[1] = 43.;
vect1[2] = 44.;
std::set<int> intset;
intset.insert(52);
intset.insert(53);
intset.insert(54);
//
typedef
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator
, std::vector<double>::iterator
>
> zit_mixed;
zit_mixed zip_it_mixed = zit_mixed(
boost::make_tuple(
intset.begin()
, vect1.begin()
)
);
boost::tuples::tuple<int, double> val_tuple(
*zip_it_mixed);
boost::tuples::tuple<const int&, double&> ref_tuple(
*zip_it_mixed);
double dblOldVal = boost::tuples::get<1>(ref_tuple);
boost::tuples::get<1>(ref_tuple) -= 41.;
if( 52 == boost::tuples::get<0>(val_tuple) &&
42. == boost::tuples::get<1>(val_tuple) &&
52 == boost::tuples::get<0>(ref_tuple) &&
1. == boost::tuples::get<1>(ref_tuple) &&
1. == *vect1.begin()
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
// Undo change to vect1
boost::tuples::get<1>(ref_tuple) = dblOldVal;
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator with 12 components
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterators with 12 components: "
<< std::flush;
// Declare 12 containers
//
std::list<int> li1;
li1.push_back(1);
std::set<int> se1;
se1.insert(2);
std::vector<int> ve1;
ve1.push_back(3);
//
std::list<int> li2;
li2.push_back(4);
std::set<int> se2;
se2.insert(5);
std::vector<int> ve2;
ve2.push_back(6);
//
std::list<int> li3;
li3.push_back(7);
std::set<int> se3;
se3.insert(8);
std::vector<int> ve3;
ve3.push_back(9);
//
std::list<int> li4;
li4.push_back(10);
std::set<int> se4;
se4.insert(11);
std::vector<int> ve4;
ve4.push_back(12);
// typedefs for cons lists of iterators.
typedef boost::tuples::cons<
std::set<int>::iterator,
boost::tuples::tuple<
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::iterator,
std::list<int>::iterator,
std::set<int>::iterator,
std::vector<int>::const_iterator
>::inherited
> cons_11_its_type;
//
typedef boost::tuples::cons<
std::list<int>::const_iterator,
cons_11_its_type
> cons_12_its_type;
// typedefs for cons lists for dereferencing the zip iterator
// made from the cons list above.
typedef boost::tuples::cons<
const int&,
boost::tuples::tuple<
int&,
int&,
const int&,
int&,
int&,
const int&,
int&,
int&,
const int&,
const int&
>::inherited
> cons_11_refs_type;
//
typedef boost::tuples::cons<
const int&,
cons_11_refs_type
> cons_12_refs_type;
// typedef for zip iterator with 12 elements
typedef boost::zip_iterator<cons_12_its_type> zip_it_12_type;
// Declare a 12-element zip iterator.
zip_it_12_type zip_it_12(
cons_12_its_type(
li1.begin(),
cons_11_its_type(
se1.begin(),
boost::make_tuple(
ve1.begin(),
li2.begin(),
se2.begin(),
ve2.begin(),
li3.begin(),
se3.begin(),
ve3.begin(),
li4.begin(),
se4.begin(),
ve4.begin()
)
)
)
);
// Dereference, mess with the result a little.
cons_12_refs_type zip_it_12_dereferenced(*zip_it_12);
boost::tuples::get<9>(zip_it_12_dereferenced) = 42;
// Make a copy and move it a little to force some instantiations.
zip_it_12_type zip_it_12_copy(zip_it_12);
++zip_it_12_copy;
if( boost::tuples::get<11>(zip_it_12.get_iterator_tuple()) == ve4.begin() &&
boost::tuples::get<11>(zip_it_12_copy.get_iterator_tuple()) == ve4.end() &&
1 == boost::tuples::get<0>(zip_it_12_dereferenced) &&
12 == boost::tuples::get<11>(zip_it_12_dereferenced) &&
42 == *(li4.begin())
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator incrementing and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator ++ and *: "
<< std::flush;
std::vector<double> vect2(3);
vect2[0] = 2.2;
vect2[1] = 3.3;
vect2[2] = 4.4;
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_begin(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_run(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
);
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_end(
boost::make_tuple(
vect1.end(),
vect2.end()
)
);
if( zip_it_run == zip_it_begin &&
42. == boost::tuples::get<0>(*zip_it_run) &&
2.2 == boost::tuples::get<1>(*zip_it_run) &&
43. == boost::tuples::get<0>(*(++zip_it_run)) &&
3.3 == boost::tuples::get<1>(*zip_it_run) &&
44. == boost::tuples::get<0>(*(++zip_it_run)) &&
4.4 == boost::tuples::get<1>(*zip_it_run) &&
zip_it_end == ++zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator decrementing and dereferencing
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator -- and *: "
<< std::flush;
if( zip_it_run == zip_it_end &&
zip_it_end == zip_it_run-- &&
44. == boost::tuples::get<0>(*zip_it_run) &&
4.4 == boost::tuples::get<1>(*zip_it_run) &&
43. == boost::tuples::get<0>(*(--zip_it_run)) &&
3.3 == boost::tuples::get<1>(*zip_it_run) &&
42. == boost::tuples::get<0>(*(--zip_it_run)) &&
2.2 == boost::tuples::get<1>(*zip_it_run) &&
zip_it_begin == zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator copy construction and equality
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator copy construction and equality: "
<< std::flush;
boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
> zip_it_run_copy(zip_it_run);
if(zip_it_run == zip_it_run && zip_it_run == zip_it_run_copy)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator inequality
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator inequality: "
<< std::flush;
if(!(zip_it_run != zip_it_run_copy) && zip_it_run != ++zip_it_run_copy)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator less than
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator less than: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run + 1
//
if( zip_it_run < zip_it_run_copy &&
!( zip_it_run < --zip_it_run_copy) &&
zip_it_run == zip_it_run_copy
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator less than or equal
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "zip iterator less than or equal: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run
//
++zip_it_run;
zip_it_run_copy += 2;
if( zip_it_run <= zip_it_run_copy &&
zip_it_run <= --zip_it_run_copy &&
!( zip_it_run <= --zip_it_run_copy) &&
zip_it_run <= zip_it_run
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator greater than
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator greater than: "
<< std::flush;
// Note: zip_it_run_copy == zip_it_run - 1
//
if( zip_it_run > zip_it_run_copy &&
!( zip_it_run > ++zip_it_run_copy) &&
zip_it_run == zip_it_run_copy
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator greater than or equal
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator greater than or equal: "
<< std::flush;
++zip_it_run;
// Note: zip_it_run == zip_it_run_copy + 1
//
if( zip_it_run >= zip_it_run_copy &&
--zip_it_run >= zip_it_run_copy &&
! (zip_it_run >= ++zip_it_run_copy)
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator + int
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator + int: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy - 1
//
zip_it_run = zip_it_run + 2;
++zip_it_run_copy;
if( zip_it_run == zip_it_run_copy && zip_it_run == zip_it_begin + 3 )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator - int
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator - int: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy, and both are at end position
//
zip_it_run = zip_it_run - 2;
--zip_it_run_copy;
--zip_it_run_copy;
if( zip_it_run == zip_it_run_copy && (zip_it_run - 1) == zip_it_begin )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator +=
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator +=: "
<< std::flush;
// Note: zip_it_run == zip_it_run_copy, and both are at begin + 1
//
zip_it_run += 2;
if( zip_it_run == zip_it_begin + 3 )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator -=
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator -=: "
<< std::flush;
// Note: zip_it_run is at end position, zip_it_run_copy is at
// begin plus one.
//
zip_it_run -= 2;
if( zip_it_run == zip_it_run_copy )
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator getting member iterators
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator member iterators: "
<< std::flush;
// Note: zip_it_run and zip_it_run_copy are both at
// begin plus one.
//
if( boost::tuples::get<0>(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 &&
boost::tuples::get<1>(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Making zip iterators
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Making zip iterators: "
<< std::flush;
std::vector<boost::tuples::tuple<double, double> >
vect_of_tuples(3);
std::copy(
boost::make_zip_iterator(
boost::make_tuple(
vect1.begin(),
vect2.begin()
)
),
boost::make_zip_iterator(
boost::make_tuple(
vect1.end(),
vect2.end()
)
),
vect_of_tuples.begin()
);
if( 42. == boost::tuples::get<0>(*vect_of_tuples.begin()) &&
2.2 == boost::tuples::get<1>(*vect_of_tuples.begin()) &&
43. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 1)) &&
3.3 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 1)) &&
44. == boost::tuples::get<0>(*(vect_of_tuples.begin() + 2)) &&
4.4 == boost::tuples::get<1>(*(vect_of_tuples.begin() + 2))
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator non-const --> const conversion
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator non-const to const conversion: "
<< std::flush;
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::const_iterator,
std::vector<double>::const_iterator
>
>
zip_it_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator,
std::vector<double>::const_iterator
>
>
zip_it_half_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
//
boost::zip_iterator<
boost::tuples::tuple<
std::set<int>::iterator,
std::vector<double>::iterator
>
>
zip_it_non_const(
boost::make_tuple(
intset.begin(),
vect2.begin()
)
);
zip_it_half_const = ++zip_it_non_const;
zip_it_const = zip_it_half_const;
++zip_it_const;
// zip_it_non_const = ++zip_it_const; // Error: can't convert from const to non-const
if( 54 == boost::tuples::get<0>(*zip_it_const) &&
4.4 == boost::tuples::get<1>(*zip_it_const) &&
53 == boost::tuples::get<0>(*zip_it_half_const) &&
3.3 == boost::tuples::get<1>(*zip_it_half_const)
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
/////////////////////////////////////////////////////////////////////////////
//
// Zip iterator categories
//
/////////////////////////////////////////////////////////////////////////////
std::cout << "Zip iterator categories: "
<< std::flush;
// The big iterator of the previous test has vector, list, and set iterators.
// Therefore, it must be bidirectional, but not random access.
bool bBigItIsBidirectionalIterator = boost::is_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::bidirectional_traversal_tag
>::value;
bool bBigItIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<zip_it_12_type>::type
, boost::random_access_traversal_tag
>::value;
// A combining iterator with all vector iterators must have random access
// traversal.
//
typedef boost::zip_iterator<
boost::tuples::tuple<
std::vector<double>::const_iterator,
std::vector<double>::const_iterator
>
> all_vects_type;
bool bAllVectsIsRandomAccessIterator = boost::is_convertible<
boost::iterator_traversal<all_vects_type>::type
, boost::random_access_traversal_tag
>::value;
// The big test.
if( bBigItIsBidirectionalIterator &&
! bBigItIsRandomAccessIterator &&
bAllVectsIsRandomAccessIterator
)
{
++num_successful_tests;
std::cout << "OK" << std::endl;
}
else
{
++num_failed_tests = 0;
std::cout << "not OK" << std::endl;
}
// Done
//
std::cout << "\nTest Result:"
<< "\n============"
<< "\nNumber of successful tests: " << static_cast<unsigned int>(num_successful_tests)
<< "\nNumber of failed tests: " << static_cast<unsigned int>(num_failed_tests)
<< std::endl;
return num_failed_tests;
}