// Copyright (c) 2014 // INRIA Saclay-Ile de France (France) // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // Author(s) : Marc Glisse #ifndef CGAL_TRANSFORMING_PAIR_ITERATOR_H #define CGAL_TRANSFORMING_PAIR_ITERATOR_H // Should be a combination of transform_iterator and zip_iterator, // but boost's iterator_category games are a pain. #include #include #include namespace CGAL { namespace internal { template ::value> struct Min_category { CGAL_static_assertion((boost::is_convertible::value)); typedef Cat1 type; }; template struct Min_category { typedef Cat2 type; }; template class transforming_pair_iterator_helper { typedef typename Min_category< typename std::iterator_traits::iterator_category, typename std::iterator_traits::iterator_category> ::type iterator_category; typedef typename Default::Get()(std::declval::reference>(),std::declval::reference>())) #else typename boost::result_of::value_type,typename std::iterator_traits::value_type)>::type // should be reference instead of value_type #endif >::type reference; typedef typename Default::Get::type>::type>::type value_type; public: typedef boost::iterator_facade< Derived, value_type, iterator_category, reference // expect ptrdiff_t is good enough for difference > type; }; } template class transforming_pair_iterator : public internal::transforming_pair_iterator_helper,F,It1,It2,Ref,Val>::type, private internal::Functor_as_base { It1 iter1; It2 iter2; friend class boost::iterator_core_access; typedef typename internal::transforming_pair_iterator_helper::type Base; typedef internal::Functor_as_base Functor_base; typename Base::reference dereference()const{ return functor()(*iter1,*iter2); } bool equal(transforming_pair_iterator const&i)const{ bool b=(iter1==i.iter1); CGAL_assertion(b==(iter2==i.iter2)); //FIXME: or do we want only one driving iterator return b; } void increment(){ ++iter1; ++iter2; } void decrement(){ --iter1; --iter2; } void advance(std::ptrdiff_t n){ std::advance(iter1,n); std::advance(iter2,n); } std::ptrdiff_t distance_to(transforming_pair_iterator const&i)const{ std::ptrdiff_t dist=std::distance(iter1,i.iter1); CGAL_assertion(dist==std::distance(iter2,i.iter2)); return dist; } public: using Functor_base::functor; transforming_pair_iterator(){} explicit transforming_pair_iterator(It1 i1,It2 i2,F const& f=F()) :Functor_base(f),iter1(i1),iter2(i2){} template transforming_pair_iterator( transforming_pair_iterator const&i, typename boost::enable_if_convertible::type* = 0, typename boost::enable_if_convertible::type* = 0, typename boost::enable_if_convertible::type* = 0) : Functor_base(i.functor()),iter1(i.iter1),iter2(i.iter2) {} }; template inline transforming_pair_iterator make_transforming_pair_iterator(It1 i1, It2 i2, F const&f=F()) { return transforming_pair_iterator(i1,i2,f); } } #endif // CGAL_TRANSFORMING_PAIR_ITERATOR_H