Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:38:53

0001 // Copyright David Abrahams and Thomas Becker 2000-2006.
0002 // Copyright Kohei Takahashi 2012-2014.
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See
0005 // accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
0009 #define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
0010 
0011 #include <utility> // for std::pair
0012 
0013 #include <boost/iterator/iterator_traits.hpp>
0014 #include <boost/iterator/iterator_facade.hpp>
0015 #include <boost/iterator/enable_if_convertible.hpp>
0016 #include <boost/iterator/iterator_categories.hpp>
0017 #include <boost/iterator/min_category.hpp>
0018 
0019 #include <boost/mp11/list.hpp>
0020 #include <boost/mp11/utility.hpp>
0021 #include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
0022 #include <boost/fusion/algorithm/iteration/for_each.hpp>
0023 #include <boost/fusion/algorithm/transformation/transform.hpp>
0024 #include <boost/fusion/sequence/convert.hpp>
0025 #include <boost/fusion/sequence/intrinsic/at_c.hpp>
0026 #include <boost/fusion/sequence/comparison/equal_to.hpp>
0027 #include <boost/fusion/support/tag_of_fwd.hpp>
0028 
0029 namespace boost {
0030 
0031 // Forward declarations for Boost.Tuple support
0032 namespace tuples {
0033 struct null_type;
0034 template< class, class >
0035 struct cons;
0036 } // namespace tuples
0037 
0038 // Forward declarations for Boost.Fusion support
0039 namespace fusion {
0040 struct void_;
0041 } // namespace fusion
0042 
0043 namespace iterators {
0044 
0045 // Zip iterator forward declaration for zip_iterator_base
0046 template< typename IteratorTuple >
0047 class zip_iterator;
0048 
0049 namespace detail {
0050 
0051 // Functors to be used with tuple algorithms
0052 //
0053 template< typename DiffType >
0054 class advance_iterator
0055 {
0056 public:
0057     advance_iterator(DiffType step) :
0058         m_step(step)
0059     {}
0060 
0061     template< typename Iterator >
0062     void operator()(Iterator& it) const { it += m_step; }
0063 
0064 private:
0065     DiffType m_step;
0066 };
0067 
0068 struct increment_iterator
0069 {
0070     template< typename Iterator >
0071     void operator()(Iterator& it) const { ++it; }
0072 };
0073 
0074 struct decrement_iterator
0075 {
0076     template< typename Iterator >
0077     void operator()(Iterator& it) const { --it; }
0078 };
0079 
0080 struct dereference_iterator
0081 {
0082     template< typename >
0083     struct result;
0084 
0085     template< typename This, typename Iterator >
0086     struct result< This(Iterator) >
0087     {
0088         using type = iterator_reference_t<
0089             typename std::remove_cv< typename std::remove_reference< Iterator >::type >::type
0090         >;
0091     };
0092 
0093     template< typename Iterator >
0094     typename result< dereference_iterator(Iterator) >::type operator()(Iterator const& it) const
0095     {
0096         return *it;
0097     }
0098 };
0099 
0100 // The trait checks if the type is a trailing "null" type used to indicate unused template parameters in non-variadic types
0101 template< typename T >
0102 struct is_trailing_null_type : std::false_type {};
0103 template< typename T >
0104 struct is_trailing_null_type< const T > : is_trailing_null_type< T > {};
0105 template< >
0106 struct is_trailing_null_type< tuples::null_type > : std::true_type {};
0107 template< >
0108 struct is_trailing_null_type< fusion::void_ > : std::true_type {};
0109 
0110 // Metafunction to obtain the type of the tuple whose element types
0111 // are the reference types of an iterator tuple.
0112 template< typename IteratorTuple >
0113 struct tuple_of_references;
0114 
0115 template< typename IteratorTuple >
0116 using tuple_of_references_t = typename tuple_of_references< IteratorTuple >::type;
0117 
0118 template< template< typename... > class Tuple, typename... Iterators >
0119 struct tuple_of_references< Tuple< Iterators... > >
0120 {
0121     // Note: non-variadic Boost.Tuple and Boost.Fusion need special handling
0122     // to avoid instantiating iterator traits on the trailing "null" types.
0123     // If not that, we could simply do
0124     // mp11::mp_transform< iterator_reference_t, IteratorTuple >.
0125     using type = Tuple<
0126         mp11::mp_eval_if<
0127             detail::is_trailing_null_type< Iterators >,
0128             Iterators,
0129             iterator_reference_t, Iterators
0130         >...
0131     >;
0132 };
0133 
0134 template< typename Front, typename Tail >
0135 struct tuple_of_references< tuples::cons< Front, Tail > >
0136 {
0137     using type = tuples::cons<
0138         iterator_reference_t< Front >,
0139         mp11::mp_eval_if<
0140             detail::is_trailing_null_type< Tail >,
0141             Tail,
0142             detail::tuple_of_references_t, Tail
0143         >
0144     >;
0145 };
0146 
0147 // Metafunction to obtain the minimal traversal tag in a list
0148 // of iterators.
0149 template< typename IteratorList >
0150 struct minimum_traversal_category_in_iterator_list;
0151 
0152 template< typename IteratorList >
0153 using minimum_traversal_category_in_iterator_list_t = typename minimum_traversal_category_in_iterator_list< IteratorList >::type;
0154 
0155 template< template< typename... > class List, typename... Iterators >
0156 struct minimum_traversal_category_in_iterator_list< List< Iterators... > >
0157 {
0158     // Note: non-variadic Boost.Tuple and Boost.Fusion need special handling
0159     // to avoid instantiating iterator traits on the trailing "null" types.
0160     // For such types just use random_access_traversal_tag, which will not
0161     // affect the result of min_category.
0162     using type = min_category_t<
0163         mp11::mp_eval_if<
0164             detail::is_trailing_null_type< Iterators >,
0165             random_access_traversal_tag,
0166             pure_iterator_traversal_t, Iterators
0167         >...
0168     >;
0169 };
0170 
0171 template< typename FrontTraversal, typename Tail >
0172 using minimum_traversal_category_in_tail_t = min_category_t<
0173     FrontTraversal,
0174     minimum_traversal_category_in_iterator_list_t< Tail >
0175 >;
0176 
0177 template< typename Front, typename Tail >
0178 struct minimum_traversal_category_in_iterator_list< tuples::cons< Front, Tail > >
0179 {
0180     using front_traversal = pure_iterator_traversal_t< Front >;
0181 
0182     using type = mp11::mp_eval_if<
0183         detail::is_trailing_null_type< Tail >,
0184         front_traversal,
0185         minimum_traversal_category_in_tail_t,
0186             front_traversal,
0187             Tail
0188     >;
0189 };
0190 
0191 ///////////////////////////////////////////////////////////////////
0192 //
0193 // Class zip_iterator_base
0194 //
0195 // Builds and exposes the iterator facade type from which the zip
0196 // iterator will be derived.
0197 //
0198 template< typename IteratorTuple >
0199 struct zip_iterator_base
0200 {
0201 private:
0202     // Reference type is the type of the tuple obtained from the
0203     // iterators' reference types.
0204     using reference = detail::tuple_of_references_t< IteratorTuple >;
0205 
0206     // Value type is the same as reference type.
0207     using value_type = reference;
0208 
0209     // Difference type is the first iterator's difference type
0210     using difference_type = iterator_difference_t< mp11::mp_front< IteratorTuple > >;
0211 
0212     // Traversal catetgory is the minimum traversal category in the
0213     // iterator tuple.
0214     using traversal_category = detail::minimum_traversal_category_in_iterator_list_t< IteratorTuple >;
0215 
0216 public:
0217     // The iterator facade type from which the zip iterator will
0218     // be derived.
0219     using type = iterator_facade<
0220         zip_iterator< IteratorTuple >,
0221         value_type,
0222         traversal_category,
0223         reference,
0224         difference_type
0225     >;
0226 };
0227 
0228 template< typename Reference >
0229 struct converter
0230 {
0231     template< typename Seq >
0232     static Reference call(Seq seq)
0233     {
0234         using tag = typename fusion::traits::tag_of< Reference >::type;
0235         return fusion::convert< tag >(seq);
0236     }
0237 };
0238 
0239 template< typename Reference1, typename Reference2 >
0240 struct converter< std::pair< Reference1, Reference2 > >
0241 {
0242     using reference = std::pair< Reference1, Reference2 >;
0243 
0244     template< typename Seq >
0245     static reference call(Seq seq)
0246     {
0247         return reference(fusion::at_c< 0 >(seq), fusion::at_c< 1 >(seq));
0248     }
0249 };
0250 
0251 } // namespace detail
0252 
0253 /////////////////////////////////////////////////////////////////////
0254 //
0255 // zip_iterator class definition
0256 //
0257 template< typename IteratorTuple >
0258 class zip_iterator :
0259     public detail::zip_iterator_base< IteratorTuple >::type
0260 {
0261     // Typedef super_t as our base class.
0262     using super_t = typename detail::zip_iterator_base< IteratorTuple >::type;
0263 
0264     // iterator_core_access is the iterator's best friend.
0265     friend class iterator_core_access;
0266 
0267 public:
0268     // Construction
0269     // ============
0270 
0271     // Default constructor
0272     zip_iterator() = default;
0273 
0274     // Constructor from iterator tuple
0275     zip_iterator(IteratorTuple iterator_tuple) :
0276         m_iterator_tuple(iterator_tuple)
0277     {}
0278 
0279     // Copy constructor
0280     template< typename OtherIteratorTuple, typename = enable_if_convertible_t< OtherIteratorTuple, IteratorTuple > >
0281     zip_iterator(zip_iterator< OtherIteratorTuple > const& other) :
0282         m_iterator_tuple(other.get_iterator_tuple())
0283     {}
0284 
0285     // Get method for the iterator tuple.
0286     IteratorTuple const& get_iterator_tuple() const { return m_iterator_tuple; }
0287 
0288 private:
0289     // Implementation of Iterator Operations
0290     // =====================================
0291 
0292     // Dereferencing returns a tuple built from the dereferenced
0293     // iterators in the iterator tuple.
0294     typename super_t::reference dereference() const
0295     {
0296         using reference = typename super_t::reference;
0297         using gen = detail::converter< reference >;
0298         return gen::call(fusion::transform(get_iterator_tuple(), detail::dereference_iterator()));
0299     }
0300 
0301     // Two zip iterators are equal if all iterators in the iterator
0302     // tuple are equal. NOTE: It should be possible to implement this
0303     // as
0304     //
0305     // return get_iterator_tuple() == other.get_iterator_tuple();
0306     //
0307     // but equality of tuples currently (7/2003) does not compile
0308     // under several compilers. No point in bringing in a bunch
0309     // of #ifdefs here.
0310     //
0311     template< typename OtherIteratorTuple >
0312     bool equal(zip_iterator< OtherIteratorTuple > const& other) const
0313     {
0314         return fusion::equal_to(get_iterator_tuple(), other.get_iterator_tuple());
0315     }
0316 
0317     // Advancing a zip iterator means to advance all iterators in the
0318     // iterator tuple.
0319     void advance(typename super_t::difference_type n)
0320     {
0321         fusion::for_each(m_iterator_tuple, detail::advance_iterator< typename super_t::difference_type >(n));
0322     }
0323 
0324     // Incrementing a zip iterator means to increment all iterators in
0325     // the iterator tuple.
0326     void increment()
0327     {
0328         fusion::for_each(m_iterator_tuple, detail::increment_iterator());
0329     }
0330 
0331     // Decrementing a zip iterator means to decrement all iterators in
0332     // the iterator tuple.
0333     void decrement()
0334     {
0335         fusion::for_each(m_iterator_tuple, detail::decrement_iterator());
0336     }
0337 
0338     // Distance is calculated using the first iterator in the tuple.
0339     template< typename OtherIteratorTuple >
0340     typename super_t::difference_type distance_to(zip_iterator< OtherIteratorTuple > const& other) const
0341     {
0342         return fusion::at_c< 0 >(other.get_iterator_tuple()) - fusion::at_c< 0 >(this->get_iterator_tuple());
0343     }
0344 
0345 private:
0346     // Data Members
0347     // ============
0348 
0349     // The iterator tuple.
0350     IteratorTuple m_iterator_tuple;
0351 };
0352 
0353 // Make function for zip iterator
0354 //
0355 template< typename IteratorTuple >
0356 inline zip_iterator< IteratorTuple > make_zip_iterator(IteratorTuple t)
0357 {
0358     return zip_iterator< IteratorTuple >(t);
0359 }
0360 
0361 } // namespace iterators
0362 
0363 using iterators::zip_iterator;
0364 using iterators::make_zip_iterator;
0365 
0366 } // namespace boost
0367 
0368 #endif