From 1ef8189af4ac8fb2036ac5cf2caf5bf2788c04c7 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Thu, 16 Feb 2006 06:23:06 +0000 Subject: [PATCH] make it work with fusion [SVN r32949] --- include/boost/iterator/zip_iterator.hpp | 359 ++++-------------------- test/zip_iterator_test.cpp | 156 +++++----- 2 files changed, 135 insertions(+), 380 deletions(-) diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp index b0eef96..4ea99d9 100755 --- a/include/boost/iterator/zip_iterator.hpp +++ b/include/boost/iterator/zip_iterator.hpp @@ -29,10 +29,9 @@ #include #include +#include #include -#include - #include #include #include @@ -40,6 +39,17 @@ #include #include #include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include namespace boost { @@ -47,24 +57,6 @@ namespace boost { template class zip_iterator; - // One important design goal of the zip_iterator is to isolate all - // functionality whose implementation relies on the current tuple - // implementation. This goal has been achieved as follows: Inside - // the namespace detail there is a namespace tuple_impl_specific. - // This namespace encapsulates all functionality that is specific - // to the current Boost tuple implementation. More precisely, the - // namespace tuple_impl_specific provides the following tuple - // algorithms and meta-algorithms for the current Boost tuple - // implementation: - // - // tuple_meta_transform - // tuple_meta_accumulate - // tuple_transform - // tuple_for_each - // - // If the tuple implementation changes, all that needs to be - // replaced is the implementation of these four (meta-)algorithms. - namespace detail { @@ -87,300 +79,64 @@ namespace boost { struct increment_iterator { template - void operator()(Iterator& it) + void operator()(Iterator& it) const { ++it; } }; // struct decrement_iterator { template - void operator()(Iterator& it) + void operator()(Iterator& it) const { --it; } }; // struct dereference_iterator { template - struct apply - { - typedef typename - iterator_traits::reference - type; - }; + struct apply : iterator_reference + {}; template - typename apply::type operator()(Iterator const& it) + typename apply::type + operator()(Iterator const& it) const { return *it; } }; - - // The namespace tuple_impl_specific provides two meta- - // algorithms and two algorithms for tuples. - // - namespace tuple_impl_specific + struct dereference { - // Meta-transform algorithm for tuples - // - template - struct tuple_meta_transform; - - template - struct tuple_meta_transform_impl - { - typedef tuples::cons< - typename mpl::apply1< - typename mpl::lambda::type - , typename Tuple::head_type - >::type - , typename tuple_meta_transform< - typename Tuple::tail_type - , UnaryMetaFun - >::type - > type; - }; + template + struct apply + : boost::iterator_reference + {}; - template - struct tuple_meta_transform - : mpl::eval_if< - boost::is_same - , mpl::identity - , tuple_meta_transform_impl - > - { - }; - - // Meta-accumulate algorithm for tuples. Note: The template - // parameter StartType corresponds to the initial value in - // ordinary accumulation. - // - template - struct tuple_meta_accumulate; - - template< - typename Tuple - , class BinaryMetaFun - , typename StartType - > - struct tuple_meta_accumulate_impl - { - typedef typename mpl::apply2< - typename mpl::lambda::type - , typename Tuple::head_type - , typename tuple_meta_accumulate< - typename Tuple::tail_type - , BinaryMetaFun - , StartType - >::type - >::type type; - }; - - template< - typename Tuple - , class BinaryMetaFun - , typename StartType - > - struct tuple_meta_accumulate - : mpl::eval_if< -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) - mpl::or_< -#endif - boost::is_same -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) - , boost::is_same - > -#endif - , mpl::identity - , tuple_meta_accumulate_impl< - Tuple - , BinaryMetaFun - , StartType - > - > - { - }; - -#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - || ( \ - BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \ - ) -// Not sure why intel's partial ordering fails in this case, but I'm -// assuming int's an MSVC bug-compatibility feature. - -# define BOOST_TUPLE_ALGO_DISPATCH -# define BOOST_TUPLE_ALGO(algo) algo##_impl -# define BOOST_TUPLE_ALGO_TERMINATOR , int -# define BOOST_TUPLE_ALGO_RECURSE , ... -#else -# define BOOST_TUPLE_ALGO(algo) algo -# define BOOST_TUPLE_ALGO_TERMINATOR -# define BOOST_TUPLE_ALGO_RECURSE -#endif - - // transform algorithm for tuples. The template parameter Fun - // must be a unary functor which is also a unary metafunction - // class that computes its return type based on its argument - // type. For example: - // - // struct to_ptr - // { - // template - // struct apply - // { - // typedef Arg* type; - // } - // - // template - // Arg* operator()(Arg x); - // }; - template - tuples::null_type BOOST_TUPLE_ALGO(tuple_transform) - (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR) - { return tuples::null_type(); } - - template - typename tuple_meta_transform< - Tuple - , Fun - >::type - - BOOST_TUPLE_ALGO(tuple_transform)( - const Tuple& t, - Fun f - BOOST_TUPLE_ALGO_RECURSE - ) - { - typedef typename tuple_meta_transform< - BOOST_DEDUCED_TYPENAME Tuple::tail_type - , Fun - >::type transformed_tail_type; - - return tuples::cons< - BOOST_DEDUCED_TYPENAME mpl::apply1< - Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type - >::type - , transformed_tail_type - >( - f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f) - ); - } - -#ifdef BOOST_TUPLE_ALGO_DISPATCH - template - typename tuple_meta_transform< - Tuple - , Fun - >::type - - tuple_transform( - const Tuple& t, - Fun f - ) - { - return tuple_transform_impl(t, f, 1); - } -#endif - - // for_each algorithm for tuples. - // - template - Fun BOOST_TUPLE_ALGO(tuple_for_each)( - tuples::null_type - , Fun f BOOST_TUPLE_ALGO_TERMINATOR - ) - { return f; } - - - template - Fun BOOST_TUPLE_ALGO(tuple_for_each)( - Tuple& t - , Fun f BOOST_TUPLE_ALGO_RECURSE) - { - f( t.get_head() ); - return tuple_for_each(t.get_tail(), f); - } - -#ifdef BOOST_TUPLE_ALGO_DISPATCH - template - Fun - tuple_for_each( - Tuple& t, - Fun f - ) - { - return tuple_for_each_impl(t, f, 1); - } -#endif - - // Equality of tuples. NOTE: "==" for tuples currently (7/2003) - // has problems under some compilers, so I just do my own. - // No point in bringing in a bunch of #ifdefs here. This is - // going to go away with the next tuple implementation anyway. - // - bool tuple_equal(tuples::null_type, tuples::null_type) - { return true; } - - template - bool tuple_equal( - Tuple1 const& t1, - Tuple2 const& t2 - ) - { - return t1.get_head() == t2.get_head() && - tuple_equal(t1.get_tail(), t2.get_tail()); - } - } - // - // end namespace tuple_impl_specific - - template - struct iterator_reference - { - typedef typename iterator_traits::reference type; + template + typename apply::type operator()(Iterator const& x) const + { + return *x; + } }; - -#ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT - // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work - // out well. Instantiating the nested apply template also - // requires instantiating iterator_traits on the - // placeholder. Instead we just specialize it as a metafunction - // class. - template<> - struct iterator_reference - { - template - struct apply : iterator_reference {}; - }; -#endif // Metafunction to obtain the type of the tuple whose element types // are the reference types of an iterator tuple. // template struct tuple_of_references - : tuple_impl_specific::tuple_meta_transform< - IteratorTuple, - iterator_reference - > - { - }; - + : mpl::transform > + {}; + // Metafunction to obtain the minimal traversal tag in a tuple // of iterators. // template struct minimum_traversal_category_in_iterator_tuple - { - typedef typename tuple_impl_specific::tuple_meta_transform< - IteratorTuple - , iterator_traversal<> - >::type tuple_of_traversal_tags; - - typedef typename tuple_impl_specific::tuple_meta_accumulate< - tuple_of_traversal_tags - , minimum_category<> - , random_access_traversal_tag - >::type type; - }; + : mpl::fold< + typename mpl::transform< + IteratorTuple, iterator_traversal<> + >::type + , random_access_traversal_tag + , minimum_category<> + > + {}; #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround template <> @@ -434,7 +190,7 @@ namespace boost { // Difference type is the first iterator's difference type typedef typename iterator_traits< - typename tuples::element<0, IteratorTuple>::type + typename mpl::front::type >::difference_type difference_type; // Traversal catetgory is the minimum traversal category in the @@ -516,10 +272,10 @@ namespace boost { // iterators in the iterator tuple. typename super_t::reference dereference() const { - return detail::tuple_impl_specific::tuple_transform( - get_iterator_tuple(), - detail::dereference_iterator() - ); + return fusion::generate(fusion::transform( + get_iterator_tuple(), + detail::dereference_iterator() + )); } // Two zip iterators are equal if all iterators in the iterator @@ -535,28 +291,25 @@ namespace boost { template bool equal(const zip_iterator& other) const { - return detail::tuple_impl_specific::tuple_equal( - get_iterator_tuple(), - other.get_iterator_tuple() - ); + return get_iterator_tuple() == other.get_iterator_tuple(); } // Advancing a zip iterator means to advance all iterators in the // iterator tuple. void advance(typename super_t::difference_type n) { - detail::tuple_impl_specific::tuple_for_each( - m_iterator_tuple, - detail::advance_iterator(n) + fusion::for_each( + m_iterator_tuple, + detail::advance_iterator(n) ); } // Incrementing a zip iterator means to increment all iterators in // the iterator tuple. void increment() { - detail::tuple_impl_specific::tuple_for_each( - m_iterator_tuple, - detail::increment_iterator() + fusion::for_each( + m_iterator_tuple, + detail::increment_iterator() ); } @@ -564,9 +317,9 @@ namespace boost { // the iterator tuple. void decrement() { - detail::tuple_impl_specific::tuple_for_each( - m_iterator_tuple, - detail::decrement_iterator() + fusion::for_each( + m_iterator_tuple, + detail::decrement_iterator() ); } @@ -576,8 +329,8 @@ namespace boost { const zip_iterator& other ) const { - return boost::tuples::get<0>(other.get_iterator_tuple()) - - boost::tuples::get<0>(this->get_iterator_tuple()); + return *fusion::begin(other.get_iterator_tuple()) - + *fusion::begin(this->get_iterator_tuple()); } // Data Members diff --git a/test/zip_iterator_test.cpp b/test/zip_iterator_test.cpp index 0e98b7d..ed3ca71 100755 --- a/test/zip_iterator_test.cpp +++ b/test/zip_iterator_test.cpp @@ -41,14 +41,19 @@ // ///////////////////////////////////////////////////////////////////////////// -#include +#define FUSION_MAX_TUPLE_SIZE 13 + #include // 2nd #include tests #include guard. #include #include #include #include #include -#include +#include +#include +#include +#include +#include #include #include #include @@ -105,32 +110,32 @@ int main( void ) typedef boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::set::iterator , std::vector::iterator > > zit_mixed; zit_mixed zip_it_mixed = zit_mixed( - boost::make_tuple( + boost::fusion::make_tuple( intset.begin() , vect1.begin() ) ); - boost::tuples::tuple val_tuple( + boost::fusion::tuple val_tuple( *zip_it_mixed); - boost::tuples::tuple ref_tuple( + boost::fusion::tuple ref_tuple( *zip_it_mixed); - double dblOldVal = boost::tuples::get<1>(ref_tuple); - boost::tuples::get<1>(ref_tuple) -= 41.; + double dblOldVal = boost::fusion::get<1>(ref_tuple); + boost::fusion::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) && + if( 52 == boost::fusion::get<0>(val_tuple) && + 42. == boost::fusion::get<1>(val_tuple) && + 52 == boost::fusion::get<0>(ref_tuple) && + 1. == boost::fusion::get<1>(ref_tuple) && 1. == *vect1.begin() ) { @@ -144,7 +149,7 @@ int main( void ) } // Undo change to vect1 - boost::tuples::get<1>(ref_tuple) = dblOldVal; + boost::fusion::get<1>(ref_tuple) = dblOldVal; ///////////////////////////////////////////////////////////////////////////// // @@ -186,9 +191,8 @@ int main( void ) ve4.push_back(12); // typedefs for cons lists of iterators. - typedef boost::tuples::cons< + typedef boost::fusion::tuple11< std::set::iterator, - boost::tuples::tuple< std::vector::iterator, std::list::iterator, std::set::iterator, @@ -199,19 +203,20 @@ int main( void ) std::list::iterator, std::set::iterator, std::vector::const_iterator - >::inherited > cons_11_its_type; + // - typedef boost::tuples::cons< - std::list::const_iterator, - cons_11_its_type - > cons_12_its_type; + typedef boost::fusion::meta::generate< + boost::fusion::meta::push_front< + cons_11_its_type, + std::list::const_iterator + >::type + >::type cons_12_its_type; // typedefs for cons lists for dereferencing the zip iterator // made from the cons list above. - typedef boost::tuples::cons< + typedef boost::fusion::tuple11< const int&, - boost::tuples::tuple< int&, int&, const int&, @@ -222,13 +227,14 @@ int main( void ) 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 boost::fusion::meta::generate< + boost::fusion::meta::push_front< + cons_11_refs_type, + const int& + >::type + >::type cons_12_refs_type; // typedef for zip iterator with 12 elements typedef boost::zip_iterator zip_it_12_type; @@ -237,9 +243,7 @@ int main( void ) 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(), @@ -250,23 +254,21 @@ int main( void ) 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; + boost::fusion::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) && + if( boost::fusion::get<11>(zip_it_12.get_iterator_tuple()) == ve4.begin() && + boost::fusion::get<11>(zip_it_12_copy.get_iterator_tuple()) == ve4.end() && + 1 == boost::fusion::get<0>(zip_it_12_dereferenced) && + 12 == boost::fusion::get<11>(zip_it_12_dereferenced) && 42 == *(li4.begin()) ) { @@ -294,51 +296,51 @@ int main( void ) vect2[2] = 4.4; boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::vector::const_iterator, std::vector::const_iterator > > zip_it_begin( - boost::make_tuple( + boost::fusion::make_tuple( vect1.begin(), vect2.begin() ) ); boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::vector::const_iterator, std::vector::const_iterator > > zip_it_run( - boost::make_tuple( + boost::fusion::make_tuple( vect1.begin(), vect2.begin() ) ); boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::vector::const_iterator, std::vector::const_iterator > > zip_it_end( - boost::make_tuple( + boost::fusion::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) && + 42. == boost::fusion::get<0>(*zip_it_run) && + 2.2 == boost::fusion::get<1>(*zip_it_run) && + 43. == boost::fusion::get<0>(*(++zip_it_run)) && + 3.3 == boost::fusion::get<1>(*zip_it_run) && + 44. == boost::fusion::get<0>(*(++zip_it_run)) && + 4.4 == boost::fusion::get<1>(*zip_it_run) && zip_it_end == ++zip_it_run ) { @@ -362,12 +364,12 @@ int main( void ) 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) && + 44. == boost::fusion::get<0>(*zip_it_run) && + 4.4 == boost::fusion::get<1>(*zip_it_run) && + 43. == boost::fusion::get<0>(*(--zip_it_run)) && + 3.3 == boost::fusion::get<1>(*zip_it_run) && + 42. == boost::fusion::get<0>(*(--zip_it_run)) && + 2.2 == boost::fusion::get<1>(*zip_it_run) && zip_it_begin == zip_it_run ) { @@ -390,7 +392,7 @@ int main( void ) << std::flush; boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::vector::const_iterator, std::vector::const_iterator > @@ -643,8 +645,8 @@ int main( void ) // 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 + if( boost::fusion::get<0>(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 && + boost::fusion::get<1>(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1 ) { ++num_successful_tests; @@ -665,18 +667,18 @@ int main( void ) std::cout << "Making zip iterators: " << std::flush; - std::vector > + std::vector > vect_of_tuples(3); std::copy( boost::make_zip_iterator( - boost::make_tuple( + boost::fusion::make_tuple( vect1.begin(), vect2.begin() ) ), boost::make_zip_iterator( - boost::make_tuple( + boost::fusion::make_tuple( vect1.end(), vect2.end() ) @@ -684,12 +686,12 @@ int main( void ) 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)) + if( 42. == boost::fusion::get<0>(*vect_of_tuples.begin()) && + 2.2 == boost::fusion::get<1>(*vect_of_tuples.begin()) && + 43. == boost::fusion::get<0>(*(vect_of_tuples.begin() + 1)) && + 3.3 == boost::fusion::get<1>(*(vect_of_tuples.begin() + 1)) && + 44. == boost::fusion::get<0>(*(vect_of_tuples.begin() + 2)) && + 4.4 == boost::fusion::get<1>(*(vect_of_tuples.begin() + 2)) ) { ++num_successful_tests; @@ -711,39 +713,39 @@ int main( void ) << std::flush; boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::set::const_iterator, std::vector::const_iterator > > zip_it_const( - boost::make_tuple( + boost::fusion::make_tuple( intset.begin(), vect2.begin() ) ); // boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::set::iterator, std::vector::const_iterator > > zip_it_half_const( - boost::make_tuple( + boost::fusion::make_tuple( intset.begin(), vect2.begin() ) ); // boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::set::iterator, std::vector::iterator > > zip_it_non_const( - boost::make_tuple( + boost::fusion::make_tuple( intset.begin(), vect2.begin() ) @@ -754,10 +756,10 @@ int main( void ) ++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) + if( 54 == boost::fusion::get<0>(*zip_it_const) && + 4.4 == boost::fusion::get<1>(*zip_it_const) && + 53 == boost::fusion::get<0>(*zip_it_half_const) && + 3.3 == boost::fusion::get<1>(*zip_it_half_const) ) { ++num_successful_tests; @@ -795,7 +797,7 @@ int main( void ) // traversal. // typedef boost::zip_iterator< - boost::tuples::tuple< + boost::fusion::tuple< std::vector::const_iterator, std::vector::const_iterator >