| // (C) Copyright Jeremy Siek 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) |
| |
| // Revision History |
| // 22 Nov 2002 Thomas Witt |
| // Added interoperability check. |
| // 28 Oct 2002 Jeremy Siek |
| // Updated for new iterator adaptors. |
| // 08 Mar 2001 Jeremy Siek |
| // Moved test of transform iterator into its own file. It to |
| // to be in iterator_adaptor_test.cpp. |
| |
| #include <boost/config.hpp> |
| #include <algorithm> |
| #include <boost/iterator/transform_iterator.hpp> |
| #include <boost/iterator/iterator_concepts.hpp> |
| #include <boost/iterator/new_iterator_tests.hpp> |
| #include <boost/pending/iterator_tests.hpp> |
| #include <boost/bind.hpp> |
| #include <boost/concept_check.hpp> |
| |
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| namespace boost { namespace detail |
| { |
| template<> struct function_object_result<int (*)(int)> |
| { |
| typedef int type; |
| }; |
| }} |
| #endif |
| |
| struct mult_functor { |
| // Functors used with transform_iterator must be |
| // DefaultConstructible, as the transform_iterator must be |
| // DefaultConstructible to satisfy the requirements for |
| // TrivialIterator. |
| mult_functor() { } |
| mult_functor(int aa) : a(aa) { } |
| int operator()(int b) const { return a * b; } |
| int a; |
| }; |
| |
| struct adaptable_mult_functor |
| : mult_functor |
| { |
| typedef int result_type; |
| typedef int argument_type; |
| // Functors used with transform_iterator must be |
| // DefaultConstructible, as the transform_iterator must be |
| // DefaultConstructible to satisfy the requirements for |
| // TrivialIterator. |
| adaptable_mult_functor() { } |
| adaptable_mult_functor(int aa) : mult_functor(aa) { } |
| }; |
| |
| |
| struct const_select_first |
| { |
| typedef int const& result_type; |
| |
| int const& operator()(std::pair<int, int>const& p) const |
| { |
| return p.first; |
| } |
| }; |
| |
| struct select_first |
| : const_select_first // derivation to allow conversions |
| { |
| typedef int& result_type; |
| |
| int& operator()(std::pair<int, int>& p) const |
| { |
| return p.first; |
| } |
| }; |
| |
| struct select_second |
| { |
| typedef int& result_type; |
| |
| int& operator()(std::pair<int, int>& p) const |
| { |
| return p.second; |
| } |
| }; |
| |
| struct value_select_first |
| { |
| typedef int result_type; |
| |
| int operator()(std::pair<int, int>const& p) const |
| { |
| return p.first; |
| } |
| }; |
| |
| int mult_2(int arg) |
| { |
| return arg*2; |
| } |
| |
| |
| int |
| main() |
| { |
| const int N = 10; |
| |
| // Concept checks |
| { |
| typedef boost::transform_iterator<adaptable_mult_functor, int*> iter_t; |
| typedef boost::transform_iterator<adaptable_mult_functor, int const*> c_iter_t; |
| |
| boost::function_requires< boost_concepts::InteroperableIteratorConcept<iter_t, c_iter_t> >(); |
| } |
| |
| // Test transform_iterator |
| { |
| int x[N], y[N]; |
| for (int k = 0; k < N; ++k) |
| x[k] = k; |
| std::copy(x, x + N, y); |
| |
| for (int k2 = 0; k2 < N; ++k2) |
| x[k2] = x[k2] * 2; |
| |
| typedef boost::transform_iterator<adaptable_mult_functor, int*> iter_t; |
| iter_t i(y, adaptable_mult_functor(2)); |
| boost::input_iterator_test(i, x[0], x[1]); |
| boost::input_iterator_test(iter_t(&y[0], adaptable_mult_functor(2)), x[0], x[1]); |
| |
| boost::random_access_readable_iterator_test(i, N, x); |
| } |
| |
| // Test transform_iterator non adaptable functor |
| { |
| int x[N], y[N]; |
| for (int k = 0; k < N; ++k) |
| x[k] = k; |
| std::copy(x, x + N, y); |
| |
| for (int k2 = 0; k2 < N; ++k2) |
| x[k2] = x[k2] * 2; |
| |
| typedef boost::transform_iterator<mult_functor, int*, int> iter_t; |
| iter_t i(y, mult_functor(2)); |
| boost::input_iterator_test(i, x[0], x[1]); |
| boost::input_iterator_test(iter_t(&y[0], mult_functor(2)), x[0], x[1]); |
| |
| boost::random_access_readable_iterator_test(i, N, x); |
| } |
| |
| // Test transform_iterator default argument handling |
| { |
| { |
| typedef boost::transform_iterator<adaptable_mult_functor, int*, float> iter_t; |
| BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, float>::value)); |
| BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, float>::value)); |
| } |
| |
| { |
| typedef boost::transform_iterator<adaptable_mult_functor, int*, boost::use_default, float> iter_t; |
| BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, int>::value)); |
| BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, float>::value)); |
| } |
| |
| { |
| typedef boost::transform_iterator<adaptable_mult_functor, int*, float, double> iter_t; |
| BOOST_STATIC_ASSERT((boost::is_same<iter_t::reference, float>::value)); |
| BOOST_STATIC_ASSERT((boost::is_same<iter_t::value_type, double>::value)); |
| } |
| } |
| |
| // Test transform_iterator with function pointers |
| { |
| int x[N], y[N]; |
| for (int k = 0; k < N; ++k) |
| x[k] = k; |
| std::copy(x, x + N, y); |
| |
| for (int k2 = 0; k2 < N; ++k2) |
| x[k2] = x[k2] * 2; |
| |
| boost::input_iterator_test( |
| boost::make_transform_iterator(y, mult_2), x[0], x[1]); |
| |
| boost::input_iterator_test( |
| boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]); |
| |
| boost::random_access_readable_iterator_test( |
| boost::make_transform_iterator(y, mult_2), N, x); |
| |
| } |
| |
| // Test transform_iterator as projection iterator |
| { |
| typedef std::pair<int, int> pair_t; |
| |
| int x[N]; |
| int y[N]; |
| pair_t values[N]; |
| |
| for(int i = 0; i < N; ++i) { |
| |
| x[i] = i; |
| y[i] = N - (i + 1); |
| |
| } |
| |
| std::copy( |
| x |
| , x + N |
| , boost::make_transform_iterator((pair_t*)values, select_first()) |
| ); |
| |
| std::copy( |
| y |
| , y + N |
| , boost::make_transform_iterator((pair_t*)values, select_second()) |
| ); |
| |
| boost::random_access_readable_iterator_test( |
| boost::make_transform_iterator((pair_t*)values, value_select_first()) |
| , N |
| , x |
| ); |
| |
| boost::random_access_readable_iterator_test( |
| boost::make_transform_iterator((pair_t*)values, const_select_first()) |
| , N, x |
| ); |
| |
| boost::constant_lvalue_iterator_test( |
| boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); |
| |
| boost::non_const_lvalue_iterator_test( |
| boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); |
| |
| boost::const_nonconst_iterator_test( |
| ++boost::make_transform_iterator((pair_t*)values, select_first()) |
| , boost::make_transform_iterator((pair_t*)values, const_select_first()) |
| ); |
| } |
| |
| return boost::report_errors(); |
| } |