1 /* Copyright 2016-2017 Joaquin M Lopez Munoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
6 * See http://www.boost.org/libs/poly_collection for library home page.
9 #ifndef BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
10 #define BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
16 #include <boost/iterator/iterator_adaptor.hpp>
17 #include <boost/iterator/iterator_facade.hpp>
18 #include <boost/poly_collection/detail/is_constructible.hpp>
19 #include <boost/poly_collection/detail/iterator_traits.hpp>
20 #include <type_traits>
25 namespace poly_collection{
29 /* Implementations of poly_collection::[const_][local_[base_]]iterator moved
30 * out of class to allow for use in deduced contexts.
33 template<typename PolyCollection,bool Const>
34 using iterator_impl_value_type=typename std::conditional<
36 const typename PolyCollection::value_type,
37 typename PolyCollection::value_type
40 template<typename PolyCollection,bool Const>
42 public boost::iterator_facade<
43 iterator_impl<PolyCollection,Const>,
44 iterator_impl_value_type<PolyCollection,Const>,
45 boost::forward_traversal_tag
48 using segment_type=typename PolyCollection::segment_type;
49 using const_segment_base_iterator=
50 typename PolyCollection::const_segment_base_iterator;
51 using const_segment_base_sentinel=
52 typename PolyCollection::const_segment_base_sentinel;
53 using const_segment_map_iterator=
54 typename PolyCollection::const_segment_map_iterator;
57 using value_type=iterator_impl_value_type<PolyCollection,Const>;
61 const_segment_map_iterator mapit,
62 const_segment_map_iterator mapend)noexcept:
63 mapit{mapit},mapend{mapend}
65 next_segment_position();
69 const_segment_map_iterator mapit_,const_segment_map_iterator mapend_,
70 const_segment_base_iterator segpos_)noexcept:
71 mapit{mapit_},mapend{mapend_},segpos{segpos_}
73 if(mapit!=mapend&&segpos==sentinel()){
75 next_segment_position();
80 iterator_impl()=default;
81 iterator_impl(const iterator_impl&)=default;
82 iterator_impl& operator=(const iterator_impl&)=default;
84 template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
85 iterator_impl(const iterator_impl<PolyCollection,Const2>& x):
86 mapit{x.mapit},mapend{x.mapend},segpos{x.segpos}{}
89 template<typename,bool>
90 friend class iterator_impl;
91 friend PolyCollection;
92 friend class boost::iterator_core_access;
94 friend struct iterator_traits;
96 value_type& dereference()const noexcept
97 {return const_cast<value_type&>(*segpos);}
98 bool equal(const iterator_impl& x)const noexcept{return segpos==x.segpos;}
100 void increment()noexcept
102 if(++segpos==sentinel()){
104 next_segment_position();
108 void next_segment_position()noexcept
110 for(;mapit!=mapend;++mapit){
111 segpos=segment().begin();
112 if(segpos!=sentinel())return;
117 segment_type& segment()noexcept
118 {return const_cast<segment_type&>(mapit->second);}
119 const segment_type& segment()const noexcept{return mapit->second;}
121 const_segment_base_sentinel sentinel()const noexcept
122 {return segment().sentinel();}
124 const_segment_map_iterator mapit,mapend;
125 const_segment_base_iterator segpos;
128 template<typename PolyCollection,bool Const>
129 struct poly_collection_of<iterator_impl<PolyCollection,Const>>
131 using type=PolyCollection;
134 template<typename PolyCollection,typename BaseIterator>
135 class local_iterator_impl:
136 public boost::iterator_adaptor<
137 local_iterator_impl<PolyCollection,BaseIterator>,
141 using segment_type=typename PolyCollection::segment_type;
142 using segment_base_iterator=typename PolyCollection::segment_base_iterator;
143 using const_segment_map_iterator=
144 typename PolyCollection::const_segment_map_iterator;
146 template<typename Iterator>
148 const_segment_map_iterator mapit,
150 local_iterator_impl::iterator_adaptor_{BaseIterator(it)},
155 using base_iterator=BaseIterator;
157 local_iterator_impl()=default;
158 local_iterator_impl(const local_iterator_impl&)=default;
159 local_iterator_impl& operator=(const local_iterator_impl&)=default;
162 typename BaseIterator2,
163 typename std::enable_if<
164 std::is_convertible<BaseIterator2,BaseIterator>::value
168 const local_iterator_impl<PolyCollection,BaseIterator2>& x):
169 local_iterator_impl::iterator_adaptor_{x.base()},
173 typename BaseIterator2,
174 typename std::enable_if<
175 !std::is_convertible<BaseIterator2,BaseIterator>::value&&
176 is_constructible<BaseIterator,BaseIterator2>::value
179 explicit local_iterator_impl(
180 const local_iterator_impl<PolyCollection,BaseIterator2>& x):
181 local_iterator_impl::iterator_adaptor_{BaseIterator(x.base())},
185 typename BaseIterator2,
186 typename std::enable_if<
187 !is_constructible<BaseIterator,BaseIterator2>::value&&
188 is_constructible<BaseIterator,segment_base_iterator>::value&&
189 is_constructible<BaseIterator2,segment_base_iterator>::value
192 explicit local_iterator_impl(
193 const local_iterator_impl<PolyCollection,BaseIterator2>& x):
194 local_iterator_impl::iterator_adaptor_{
195 base_iterator_from(x.segment(),x.base())},
198 /* define [] to avoid Boost.Iterator operator_brackets_proxy mess */
200 template<typename DifferenceType>
201 typename std::iterator_traits<BaseIterator>::reference
202 operator[](DifferenceType n)const{return *(*this+n);}
205 template<typename,typename>
206 friend class local_iterator_impl;
207 friend PolyCollection;
209 friend struct iterator_traits;
211 template<typename BaseIterator2>
212 static BaseIterator base_iterator_from(
213 const segment_type& s,BaseIterator2 it)
215 segment_base_iterator bit=s.begin();
216 return BaseIterator{bit+(it-static_cast<BaseIterator2>(bit))};
219 base_iterator base()const noexcept
220 {return local_iterator_impl::iterator_adaptor_::base();}
221 const std::type_info& type_info()const{return *mapit->first;}
222 segment_type& segment()noexcept
223 {return const_cast<segment_type&>(mapit->second);}
224 const segment_type& segment()const noexcept{return mapit->second;}
226 const_segment_map_iterator mapit;
229 template<typename PolyCollection,typename BaseIterator>
230 struct poly_collection_of<local_iterator_impl<PolyCollection,BaseIterator>>
232 using type=PolyCollection;
236 } /* namespace poly_collection::detail */
238 } /* namespace poly_collection */
240 } /* namespace boost */