Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:22:15

0001 /* Copyright 2016-2021 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/poly_collection for library home page.
0007  */
0008 
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/detail/workaround.hpp>
0017 #include <boost/iterator/iterator_adaptor.hpp>
0018 #include <boost/iterator/iterator_facade.hpp>
0019 #include <boost/poly_collection/detail/is_constructible.hpp>
0020 #include <boost/poly_collection/detail/iterator_traits.hpp>
0021 #include <type_traits>
0022 #include <typeinfo>
0023 
0024 namespace boost{
0025 
0026 namespace poly_collection{
0027 
0028 namespace detail{
0029 
0030 /* Implementations of poly_collection::[const_][local_[base_]]iterator moved
0031  * out of class to allow for use in deduced contexts.
0032  */
0033 
0034 template<typename PolyCollection,bool Const>
0035 using iterator_impl_value_type=typename std::conditional<
0036   Const,
0037   const typename PolyCollection::value_type,
0038   typename PolyCollection::value_type
0039 >::type;
0040 
0041 template<typename PolyCollection,bool Const>
0042 class iterator_impl:
0043   public boost::iterator_facade<
0044     iterator_impl<PolyCollection,Const>,
0045     iterator_impl_value_type<PolyCollection,Const>,
0046     boost::forward_traversal_tag
0047   >
0048 {
0049   using segment_type=typename PolyCollection::segment_type;
0050   using const_segment_base_iterator=
0051     typename PolyCollection::const_segment_base_iterator;
0052   using const_segment_base_sentinel=
0053     typename PolyCollection::const_segment_base_sentinel;
0054   using const_segment_map_iterator=
0055     typename PolyCollection::const_segment_map_iterator;
0056 
0057 public:
0058   using value_type=iterator_impl_value_type<PolyCollection,Const>;
0059 
0060 private:
0061   iterator_impl(
0062     const_segment_map_iterator mapit,
0063     const_segment_map_iterator mapend)noexcept:
0064     mapit{mapit},mapend{mapend}
0065   {
0066     next_segment_position();
0067   }
0068 
0069   iterator_impl(
0070     const_segment_map_iterator mapit_,const_segment_map_iterator mapend_,
0071     const_segment_base_iterator segpos_)noexcept:
0072     mapit{mapit_},mapend{mapend_},segpos{segpos_}
0073   {
0074     if(mapit!=mapend&&segpos==sentinel()){
0075       ++mapit;
0076       next_segment_position();
0077     }
0078   }
0079 
0080 public:
0081   iterator_impl()=default;
0082   iterator_impl(const iterator_impl&)=default;
0083   iterator_impl& operator=(const iterator_impl&)=default;
0084 
0085   template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
0086   iterator_impl(const iterator_impl<PolyCollection,Const2>& x):
0087     mapit{x.mapit},mapend{x.mapend},segpos{x.segpos}{}
0088       
0089 private:
0090   template<typename,bool>
0091   friend class iterator_impl;
0092   friend PolyCollection;
0093   friend class boost::iterator_core_access;
0094   template<typename>
0095   friend struct iterator_traits;
0096 
0097   value_type& dereference()const noexcept
0098     {return const_cast<value_type&>(*segpos);}
0099   bool equal(const iterator_impl& x)const noexcept{return segpos==x.segpos;}
0100 
0101   void increment()noexcept
0102   {
0103     if(++segpos==sentinel()){
0104       ++mapit;
0105       next_segment_position();
0106     }
0107   }
0108 
0109   void next_segment_position()noexcept
0110   {
0111     for(;mapit!=mapend;++mapit){
0112       segpos=segment().begin();
0113       if(segpos!=sentinel())return;
0114     }
0115     segpos=nullptr;
0116   }
0117 
0118   segment_type&       segment()noexcept
0119     {return const_cast<segment_type&>(mapit->second);}
0120   const segment_type& segment()const noexcept{return mapit->second;}
0121 
0122   const_segment_base_sentinel sentinel()const noexcept
0123     {return segment().sentinel();}
0124 
0125   const_segment_map_iterator  mapit,mapend;
0126   const_segment_base_iterator segpos;
0127 };
0128 
0129 template<typename PolyCollection,bool Const>
0130 struct poly_collection_of<iterator_impl<PolyCollection,Const>>
0131 {
0132   using type=PolyCollection;
0133 };
0134 
0135 template<typename PolyCollection,typename BaseIterator>
0136 class local_iterator_impl:
0137   public boost::iterator_adaptor<
0138     local_iterator_impl<PolyCollection,BaseIterator>,
0139     BaseIterator
0140   >
0141 {
0142   using segment_type=typename PolyCollection::segment_type;
0143   using segment_base_iterator=typename PolyCollection::segment_base_iterator;
0144   using const_segment_map_iterator=
0145     typename PolyCollection::const_segment_map_iterator;
0146 
0147 #if BOOST_WORKAROUND(BOOST_GCC_VERSION,>=90300)&&\
0148     BOOST_WORKAROUND(BOOST_GCC_VERSION,<100300)
0149 /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95888 */
0150 
0151 public:
0152 #else
0153 private:
0154 #endif
0155 
0156   template<typename Iterator>
0157   local_iterator_impl(
0158     const_segment_map_iterator mapit,
0159     Iterator it):
0160     local_iterator_impl::iterator_adaptor_{BaseIterator(it)},
0161     mapit{mapit}
0162   {}
0163 
0164 public:
0165   using base_iterator=BaseIterator;
0166 
0167   local_iterator_impl()=default;
0168   local_iterator_impl(const local_iterator_impl&)=default;
0169   local_iterator_impl& operator=(const local_iterator_impl&)=default;
0170 
0171   template<
0172     typename BaseIterator2,
0173     typename std::enable_if<
0174       std::is_convertible<BaseIterator2,BaseIterator>::value
0175     >::type* =nullptr
0176   >
0177   local_iterator_impl(
0178     const local_iterator_impl<PolyCollection,BaseIterator2>& x):
0179     local_iterator_impl::iterator_adaptor_{x.base()},
0180     mapit{x.mapit}{}
0181 
0182   template<
0183     typename BaseIterator2,
0184     typename std::enable_if<
0185       !std::is_convertible<BaseIterator2,BaseIterator>::value&&
0186       is_constructible<BaseIterator,BaseIterator2>::value
0187     >::type* =nullptr
0188   >
0189   explicit local_iterator_impl(
0190     const local_iterator_impl<PolyCollection,BaseIterator2>& x):
0191     local_iterator_impl::iterator_adaptor_{BaseIterator(x.base())},
0192     mapit{x.mapit}{}
0193 
0194   template<
0195     typename BaseIterator2,
0196     typename std::enable_if<
0197       !is_constructible<BaseIterator,BaseIterator2>::value&&
0198       is_constructible<BaseIterator,segment_base_iterator>::value&&
0199       is_constructible<BaseIterator2,segment_base_iterator>::value
0200     >::type* =nullptr
0201   >
0202   explicit local_iterator_impl(
0203     const local_iterator_impl<PolyCollection,BaseIterator2>& x):
0204     local_iterator_impl::iterator_adaptor_{
0205       base_iterator_from(x.segment(),x.base())},
0206     mapit{x.mapit}{}
0207 
0208   /* define [] to avoid Boost.Iterator operator_brackets_proxy mess */
0209 
0210   template<typename DifferenceType>
0211   typename std::iterator_traits<BaseIterator>::reference
0212   operator[](DifferenceType n)const{return *(*this+n);}
0213 
0214 private:
0215   template<typename,typename>
0216   friend class local_iterator_impl;
0217   friend PolyCollection;
0218   template<typename>
0219   friend struct iterator_traits;
0220 
0221   template<typename BaseIterator2>
0222   static BaseIterator base_iterator_from(
0223     const segment_type& s,BaseIterator2 it)
0224   {
0225     segment_base_iterator bit=s.begin();
0226     return BaseIterator{bit+(it-static_cast<BaseIterator2>(bit))};
0227   } 
0228 
0229   base_iterator              base()const noexcept
0230     {return local_iterator_impl::iterator_adaptor_::base();}
0231   const std::type_info&      type_info()const{return *mapit->first;}
0232   segment_type&              segment()noexcept
0233     {return const_cast<segment_type&>(mapit->second);}
0234   const segment_type&        segment()const noexcept{return mapit->second;}
0235 
0236   const_segment_map_iterator mapit;
0237 };
0238 
0239 template<typename PolyCollection,typename BaseIterator>
0240 struct poly_collection_of<local_iterator_impl<PolyCollection,BaseIterator>>
0241 {
0242   using type=PolyCollection;
0243 };
0244 
0245 } /* namespace poly_collection::detail */
0246 
0247 } /* namespace poly_collection */
0248 
0249 } /* namespace boost */
0250 
0251 #endif