diff --git a/test/Jamfile b/test/Jamfile index b206bde..fa1d6e1 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -46,17 +46,16 @@ test-suite iterator [ run reverse_iterator_test.cpp ] [ run counting_iterator_test.cpp ] [ run interoperable.cpp ] + [ run iterator_traits_test.cpp ] [ run permutation_iterator_test.cpp : : : # on ] - [ run ../../utility/iterator_adaptor_examples.cpp ] - [ run ../../utility/counting_iterator_example.cpp ] - [ run ../../utility/filter_iterator_example.cpp ] - [ run ../../utility/fun_out_iter_example.cpp ] - [ run ../../utility/indirect_iterator_example.cpp ] - [ run ../../utility/projection_iterator_example.cpp ] - [ run ../../utility/reverse_iterator_example.cpp ] - [ run ../../utility/transform_iterator_example.cpp ] - [ run ../../utility/iterator_traits_test.cpp ] - [ run ../../utility/shared_iterator_test.cpp ] + [ run iterator_adaptor_examples.cpp ] + [ run counting_iterator_example.cpp ] + [ run filter_iterator_example.cpp ] + [ run fun_out_iter_example.cpp ] + [ run indirect_iterator_example.cpp ] + [ run projection_iterator_example.cpp ] + [ run reverse_iterator_example.cpp ] + [ run transform_iterator_example.cpp ] ; diff --git a/test/counting_iterator_example.cpp b/test/counting_iterator_example.cpp new file mode 100644 index 0000000..6bc341a --- /dev/null +++ b/test/counting_iterator_example.cpp @@ -0,0 +1,60 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + + +#include +#include +#include +#include +#include +#include +#include + +int main(int, char*[]) +{ + // Example of using counting_iterator_generator + std::cout << "counting from 0 to 4:" << std::endl; + boost::counting_iterator first(0), last(4); + std::copy(first, last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Example of using make_counting_iterator() + std::cout << "counting from -5 to 4:" << std::endl; + std::copy(boost::make_counting_iterator(-5), + boost::make_counting_iterator(5), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Example of using counting iterator to create an array of pointers. +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + const +#endif + int N = 7; + std::vector numbers; + // Fill "numbers" array with [0,N) + std::copy( + boost::make_counting_iterator(0) + , boost::make_counting_iterator(N) + , std::back_inserter(numbers)); + + std::vector::iterator> pointers; + + // Use counting iterator to fill in the array of pointers. + // causes an ICE with MSVC6 + std::copy(boost::make_counting_iterator(numbers.begin()), + boost::make_counting_iterator(numbers.end()), + std::back_inserter(pointers)); + + // Use indirect iterator to print out numbers by accessing + // them through the array of pointers. + std::cout << "indirectly printing out the numbers from 0 to " + << N << std::endl; + std::copy(boost::make_indirect_iterator(pointers.begin()), + boost::make_indirect_iterator(pointers.end()), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + return 0; +} diff --git a/test/filter_iterator_example.cpp b/test/filter_iterator_example.cpp new file mode 100644 index 0000000..35e806f --- /dev/null +++ b/test/filter_iterator_example.cpp @@ -0,0 +1,61 @@ +// Example of using the filter iterator adaptor from +// boost/iterator_adaptors.hpp. + +// (C) Copyright Jeremy Siek 1999. +// 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) + +#include +#include +#include +#include +#include + +struct is_positive_number { + bool operator()(int x) { return 0 < x; } +}; + +int main() +{ + int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 }; + const int N = sizeof(numbers_)/sizeof(int); + + typedef int* base_iterator; + base_iterator numbers(numbers_); + + // Example using make_filter_iterator() + std::copy(boost::make_filter_iterator(numbers, numbers + N), + boost::make_filter_iterator(numbers + N, numbers + N), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Example using filter_iterator + typedef boost::filter_iterator + FilterIter; + + is_positive_number predicate; + FilterIter filter_iter_first(predicate, numbers, numbers + N); + FilterIter filter_iter_last(predicate, numbers + N, numbers + N); + + std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Another example using make_filter_iterator() + std::copy( + boost::make_filter_iterator( + std::bind2nd(std::greater(), -2) + , numbers, numbers + N) + + , boost::make_filter_iterator( + std::bind2nd(std::greater(), -2) + , numbers + N, numbers + N) + + , std::ostream_iterator(std::cout, " ") + ); + + std::cout << std::endl; + + + return 0; +} diff --git a/test/fun_out_iter_example.cpp b/test/fun_out_iter_example.cpp new file mode 100644 index 0000000..233fe9b --- /dev/null +++ b/test/fun_out_iter_example.cpp @@ -0,0 +1,46 @@ +// (C) Copyright Jeremy Siek 2001. +// 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) + +// Revision History: + +// 27 Feb 2001 Jeremy Siek +// Initial checkin. + +#include +#include +#include + +#include + +struct string_appender +{ + string_appender(std::string& s) + : m_str(&s) + {} + + void operator()(const std::string& x) const + { + *m_str += x; + } + + std::string* m_str; +}; + +int main(int, char*[]) +{ + std::vector x; + x.push_back("hello"); + x.push_back(" "); + x.push_back("world"); + x.push_back("!"); + + std::string s = ""; + std::copy(x.begin(), x.end(), + boost::make_function_output_iterator(string_appender(s))); + + std::cout << s << std::endl; + + return 0; +} diff --git a/test/indirect_iterator_example.cpp b/test/indirect_iterator_example.cpp new file mode 100644 index 0000000..a6f5666 --- /dev/null +++ b/test/indirect_iterator_example.cpp @@ -0,0 +1,59 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + +#include +#include +#include +#include +#include +#include +#include + +int main(int, char*[]) +{ + char characters[] = "abcdefg"; + const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char + char* pointers_to_chars[N]; // at the end. + for (int i = 0; i < N; ++i) + pointers_to_chars[i] = &characters[i]; + + // Example of using indirect_iterator_generator + + boost::indirect_iterator + indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); + + std::copy(indirect_first, indirect_last, std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of using indirect_iterator_pair_generator + + char mutable_characters[N]; + char* pointers_to_mutable_chars[N]; + for (int j = 0; j < N; ++j) + pointers_to_mutable_chars[j] = &mutable_characters[j]; + + boost::indirect_iterator mutable_indirect_first(pointers_to_mutable_chars), + mutable_indirect_last(pointers_to_mutable_chars + N); + boost::indirect_iterator const_indirect_first(pointers_to_chars), + const_indirect_last(pointers_to_chars + N); + + std::transform(const_indirect_first, const_indirect_last, + mutable_indirect_first, std::bind1st(std::plus(), 1)); + + std::copy(mutable_indirect_first, mutable_indirect_last, + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of using make_indirect_iterator() + + std::copy(boost::make_indirect_iterator(pointers_to_chars), + boost::make_indirect_iterator(pointers_to_chars + N), + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + return 0; +} diff --git a/test/iterator_adaptor_examples.cpp b/test/iterator_adaptor_examples.cpp new file mode 100644 index 0000000..3bf90d3 --- /dev/null +++ b/test/iterator_adaptor_examples.cpp @@ -0,0 +1,46 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + + +#include +#include +#include +#include +#include + +int +main(int, char*[]) +{ + // This is a simple example of using the transform_iterators class to + // generate iterators that multiply the value returned by dereferencing + // the iterator. In this case we are multiplying by 2. + // Would be cooler to use lambda library in this example. + + int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + typedef std::binder1st< std::multiplies > Function; + + typedef boost::transform_iterator doubling_iterator; + + doubling_iterator i(x, std::bind1st(std::multiplies(), 2)), + i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies(), 2)); + + std::cout << "multiplying the array by 2:" << std::endl; + while (i != i_end) + std::cout << *i++ << " "; + std::cout << std::endl; + + // Here is an example of counting from 0 to 5 using the integer_range class. + + boost::integer_range r(0,5); + + std::cout << "counting to from 0 to 4:" << std::endl; + std::copy(r.begin(), r.end(), std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + return 0; +} + + diff --git a/test/iterator_traits_test.cpp b/test/iterator_traits_test.cpp new file mode 100644 index 0000000..803f59b --- /dev/null +++ b/test/iterator_traits_test.cpp @@ -0,0 +1,214 @@ +// (C) Copyright David Abrahams 2002. +// 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) + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 04 Mar 2001 Patches for Intel C++ (Dave Abrahams) +// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests +// on MSVC. Reordered some #ifdefs for coherency. +// (David Abrahams) +// 13 Feb 2001 Test new VC6 workarounds (David Abrahams) +// 11 Feb 2001 Final fixes for Borland (David Abrahams) +// 11 Feb 2001 Some fixes for Borland get it closer on that compiler +// (David Abrahams) +// 07 Feb 2001 More comprehensive testing; factored out static tests for +// better reuse (David Abrahams) +// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a +// reference type from operator* (David Abrahams) +// 19 Jan 2001 Initial version with iterator operators (David Abrahams) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// A UDT for which we can specialize std::iterator_traits on +// compilers which don't support partial specialization. There's no +// other reasonable way to test pointers on those compilers. +struct element {}; + +// An iterator for which we can get traits. +struct my_iterator1 + : boost::forward_iterator_helper +{ + my_iterator1(const char* p) : m_p(p) {} + + bool operator==(const my_iterator1& rhs) const + { return this->m_p == rhs.m_p; } + + my_iterator1& operator++() { ++this->m_p; return *this; } + const char& operator*() { return *m_p; } + private: + const char* m_p; +}; + +// Used to prove that we don't require std::iterator<> in the hierarchy under +// MSVC6, and that we can compute all the traits for a standard-conforming UDT +// iterator. +struct my_iterator2 + : boost::equality_comparable > > +{ + typedef char value_type; + typedef long difference_type; + typedef const char* pointer; + typedef const char& reference; + typedef std::forward_iterator_tag iterator_category; + + my_iterator2(const char* p) : m_p(p) {} + + bool operator==(const my_iterator2& rhs) const + { return this->m_p == rhs.m_p; } + + my_iterator2& operator++() { ++this->m_p; return *this; } + const char& operator*() { return *m_p; } + private: + const char* m_p; +}; + +// Used to prove that we're not overly confused by the existence of +// std::iterator<> in the hierarchy under MSVC6 - we should find that +// boost::detail::iterator_traits::difference_type is int. +struct my_iterator3 : my_iterator1 +{ + typedef int difference_type; + my_iterator3(const char* p) + : my_iterator1(p) {} +}; + +// +// Assertion tools. Used instead of BOOST_STATIC_ASSERT because that +// doesn't give us a nice stack backtrace +// +template struct assertion; + +template <> struct assertion +{ + typedef char type; +}; + +template +struct assert_same + : assertion<(::boost::is_same::value)> +{ +}; + + +// Iterator tests +template +struct non_portable_tests +{ + typedef typename boost::detail::iterator_traits::pointer test_pt; + typedef typename boost::detail::iterator_traits::reference test_rt; + typedef typename assert_same::type a1; + typedef typename assert_same::type a2; +}; + +template +struct portable_tests +{ + typedef typename boost::detail::iterator_traits::difference_type test_dt; + typedef typename boost::detail::iterator_traits::iterator_category test_cat; + typedef typename assert_same::type a1; + typedef typename assert_same::type a2; +}; + +// Test iterator_traits +template +struct input_iterator_test + : portable_tests +{ + typedef typename boost::detail::iterator_traits::value_type test_vt; + typedef typename assert_same::type a1; +}; + +template +struct non_pointer_test + : input_iterator_test + , non_portable_tests +{ +}; + +template +struct maybe_pointer_test + : portable_tests + , non_portable_tests +{ +}; + +input_iterator_test, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag> + istream_iterator_test; + +#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT) +typedef ::std::char_traits::off_type distance; +non_pointer_test,int, + distance,int*,int&,std::output_iterator_tag> ostream_iterator_test; +#elif defined(BOOST_MSVC_STD_ITERATOR) +non_pointer_test, + int, void, int*, int&, std::output_iterator_tag> + ostream_iterator_test; +#else +non_pointer_test, + void, void, void, void, std::output_iterator_tag> + ostream_iterator_test; +#endif + + +#ifdef __KCC + typedef long std_list_diff_type; +#else + typedef std::ptrdiff_t std_list_diff_type; +#endif + +non_pointer_test::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag> + list_iterator_test; + +maybe_pointer_test::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag> + vector_iterator_test; + +maybe_pointer_test + int_pointer_test; + +non_pointer_test + my_iterator1_test; + +non_pointer_test + my_iterator2_test; + +non_pointer_test + my_iterator3_test; + +int main() +{ + char chars[100]; + int ints[100]; + + for (int length = 3; length < 100; length += length / 3) + { + std::list l(length); + assert(boost::detail::distance(l.begin(), l.end()) == length); + + std::vector v(length); + assert(boost::detail::distance(v.begin(), v.end()) == length); + + assert(boost::detail::distance(&ints[0], ints + length) == length); + assert(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length); + assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length); + assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length); + } + return 0; +} diff --git a/test/projection_iterator_example.cpp b/test/projection_iterator_example.cpp new file mode 100644 index 0000000..3440fbf --- /dev/null +++ b/test/projection_iterator_example.cpp @@ -0,0 +1,103 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + +#include +#include +#include +#include +#include +#include +#include + +struct personnel_record { + personnel_record(std::string n, int id) : m_name(n), m_ID(id) { } + std::string m_name; + int m_ID; +}; + +struct select_name { + typedef personnel_record argument_type; + typedef std::string const& result_type; + const std::string& operator()(const personnel_record& r) const { + return r.m_name; + } + std::string& operator()(personnel_record& r) const { + return r.m_name; + } +}; + +struct select_ID { + typedef personnel_record argument_type; + typedef int& result_type; + const int& operator()(const personnel_record& r) const { + return r.m_ID; + } + int& operator()(personnel_record& r) const { + return r.m_ID; + } +}; + +int main(int, char*[]) +{ + std::list personnel_list; + + personnel_list.push_back(personnel_record("Barney", 13423)); + personnel_list.push_back(personnel_record("Fred", 12343)); + personnel_list.push_back(personnel_record("Wilma", 62454)); + personnel_list.push_back(personnel_record("Betty", 20490)); + + // Example of using transform_iterator to print out the names in the + // personnel list using a projection. + + boost::transform_iterator< + select_name + , std::list::iterator +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + , std::string +#endif + > + personnel_first(personnel_list.begin()), + personnel_last(personnel_list.end()); + + std::copy(personnel_first, personnel_last, + std::ostream_iterator(std::cout, "\n")); + std::cout << std::endl; + + // Example of using transform_iterator with const_iterators to + // assign new ID numbers to the personnel. + + boost::transform_iterator< + select_ID, std::list::iterator + > ID_first(personnel_list.begin()), + ID_last(personnel_list.end()); + + int new_id = 0; + while (ID_first != ID_last) { + *ID_first = new_id++; + ++ID_first; + } + + boost::transform_iterator< + select_ID, std::list::const_iterator, int const& + > + const_ID_first(personnel_list.begin()), + const_ID_last(personnel_list.end()); + + std::copy(const_ID_first, const_ID_last, + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + std::cout << std::endl; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // Example of using make_const_projection_iterator() + // to print out the names in the personnel list again. + std::copy( + boost::make_transform_iterator(personnel_list.begin()) + , boost::make_transform_iterator(personnel_list.end()) + , std::ostream_iterator(std::cout, "\n")); +#endif + + return 0; +} diff --git a/test/reverse_iterator_example.cpp b/test/reverse_iterator_example.cpp new file mode 100644 index 0000000..e77b9ac --- /dev/null +++ b/test/reverse_iterator_example.cpp @@ -0,0 +1,47 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + +#include +#include +#include +#include +#include + +//boost::detail::iterator_traits +int main(int, char*[]) +{ + char letters_[] = "hello world!"; + const int N = sizeof(letters_)/sizeof(char) - 1; + typedef char* base_iterator; + base_iterator letters(letters_); + + std::cout << "original sequence of letters:\t" + << letters_ << std::endl; + + std::sort(letters, letters + N); + + // Use reverse_iterator_generator to print a sequence + // of letters in reverse order. + + boost::reverse_iterator + reverse_letters_first(letters + N), + reverse_letters_last(letters); + + std::cout << "letters in descending order:\t"; + std::copy(reverse_letters_first, reverse_letters_last, + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + // Use make_reverse_iterator() to print the sequence + // of letters in reverse-reverse order. + + std::cout << "letters in ascending order:\t"; + std::copy(boost::make_reverse_iterator(reverse_letters_last), + boost::make_reverse_iterator(reverse_letters_first), + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + return 0; +} diff --git a/test/transform_iterator_example.cpp b/test/transform_iterator_example.cpp new file mode 100644 index 0000000..71e09f0 --- /dev/null +++ b/test/transform_iterator_example.cpp @@ -0,0 +1,76 @@ +// (C) Copyright Jeremy Siek 2000. +// 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) + + +#include +#include +#include +#include + +// What a bummer. We can't use std::binder1st with transform iterator +// because it does not have a default constructor. Here's a version +// that does. + +namespace boost { + + template + class binder1st + : public std::unary_function { + protected: + Operation op; + typename Operation::first_argument_type value; + public: + binder1st() { } // this had to be added! + binder1st(const Operation& x, + const typename Operation::first_argument_type& y) + : op(x), value(y) {} + typename Operation::result_type + operator()(const typename Operation::second_argument_type& x) const { + return op(value, x); + } + }; + + template + inline binder1st bind1st(const Operation& op, const T& x) { + typedef typename Operation::first_argument_type arg1_type; + return binder1st(op, arg1_type(x)); + } + +} // namespace boost + +int +main(int, char*[]) +{ + // This is a simple example of using the transform_iterators class to + // generate iterators that multiply the value returned by dereferencing + // the iterator. In this case we are multiplying by 2. + // Would be cooler to use lambda library in this example. + + int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + const int N = sizeof(x)/sizeof(int); + + typedef boost::binder1st< std::multiplies > Function; + typedef boost::transform_iterator doubling_iterator; + + doubling_iterator i(x, boost::bind1st(std::multiplies(), 2)), + i_end(x + N, boost::bind1st(std::multiplies(), 2)); + + std::cout << "multiplying the array by 2:" << std::endl; + while (i != i_end) + std::cout << *i++ << " "; + std::cout << std::endl; + + std::cout << "adding 4 to each element in the array:" << std::endl; + + std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus(), 4)), + boost::make_transform_iterator(x + N, boost::bind1st(std::plus(), 4)), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + return 0; +} + +