1/* Copyright 2016-2021 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)
5 *
6 * See http://www.boost.org/libs/poly_collection for library home page.
7 */
8
9#ifndef BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
10#define BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
11
12#if defined(_MSC_VER)
13#pragma once
14#endif
15
16#include <boost/detail/workaround.hpp>
17#include <boost/iterator/iterator_adaptor.hpp>
18#include <boost/iterator/iterator_facade.hpp>
19#include <boost/poly_collection/detail/is_constructible.hpp>
20#include <boost/poly_collection/detail/iterator_traits.hpp>
21#include <type_traits>
22#include <typeinfo>
23
24namespace boost{
25
26namespace poly_collection{
27
28namespace detail{
29
30/* Implementations of poly_collection::[const_][local_[base_]]iterator moved
31 * out of class to allow for use in deduced contexts.
32 */
33
34template<typename PolyCollection,bool Const>
35using iterator_impl_value_type=typename std::conditional<
36 Const,
37 const typename PolyCollection::value_type,
38 typename PolyCollection::value_type
39>::type;
40
41template<typename PolyCollection,bool Const>
42class iterator_impl:
43 public boost::iterator_facade<
44 iterator_impl<PolyCollection,Const>,
45 iterator_impl_value_type<PolyCollection,Const>,
46 boost::forward_traversal_tag
47 >
48{
49 using segment_type=typename PolyCollection::segment_type;
50 using const_segment_base_iterator=
51 typename PolyCollection::const_segment_base_iterator;
52 using const_segment_base_sentinel=
53 typename PolyCollection::const_segment_base_sentinel;
54 using const_segment_map_iterator=
55 typename PolyCollection::const_segment_map_iterator;
56
57public:
58 using value_type=iterator_impl_value_type<PolyCollection,Const>;
59
60private:
61 iterator_impl(
62 const_segment_map_iterator mapit,
63 const_segment_map_iterator mapend)noexcept:
64 mapit{mapit},mapend{mapend}
65 {
66 next_segment_position();
67 }
68
69 iterator_impl(
70 const_segment_map_iterator mapit_,const_segment_map_iterator mapend_,
71 const_segment_base_iterator segpos_)noexcept:
72 mapit{mapit_},mapend{mapend_},segpos{segpos_}
73 {
74 if(mapit!=mapend&&segpos==sentinel()){
75 ++mapit;
76 next_segment_position();
77 }
78 }
79
80public:
81 iterator_impl()=default;
82 iterator_impl(const iterator_impl&)=default;
83 iterator_impl& operator=(const iterator_impl&)=default;
84
85 template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
86 iterator_impl(const iterator_impl<PolyCollection,Const2>& x):
87 mapit{x.mapit},mapend{x.mapend},segpos{x.segpos}{}
88
89private:
90 template<typename,bool>
91 friend class iterator_impl;
92 friend PolyCollection;
93 friend class boost::iterator_core_access;
94 template<typename>
95 friend struct iterator_traits;
96
97 value_type& dereference()const noexcept
98 {return const_cast<value_type&>(*segpos);}
99 bool equal(const iterator_impl& x)const noexcept{return segpos==x.segpos;}
100
101 void increment()noexcept
102 {
103 if(++segpos==sentinel()){
104 ++mapit;
105 next_segment_position();
106 }
107 }
108
109 void next_segment_position()noexcept
110 {
111 for(;mapit!=mapend;++mapit){
112 segpos=segment().begin();
113 if(segpos!=sentinel())return;
114 }
115 segpos=nullptr;
116 }
117
118 segment_type& segment()noexcept
119 {return const_cast<segment_type&>(mapit->second);}
120 const segment_type& segment()const noexcept{return mapit->second;}
121
122 const_segment_base_sentinel sentinel()const noexcept
123 {return segment().sentinel();}
124
125 const_segment_map_iterator mapit,mapend;
126 const_segment_base_iterator segpos;
127};
128
129template<typename PolyCollection,bool Const>
130struct poly_collection_of<iterator_impl<PolyCollection,Const>>
131{
132 using type=PolyCollection;
133};
134
135template<typename PolyCollection,typename BaseIterator>
136class local_iterator_impl:
137 public boost::iterator_adaptor<
138 local_iterator_impl<PolyCollection,BaseIterator>,
139 BaseIterator
140 >
141{
142 using segment_type=typename PolyCollection::segment_type;
143 using segment_base_iterator=typename PolyCollection::segment_base_iterator;
144 using const_segment_map_iterator=
145 typename PolyCollection::const_segment_map_iterator;
146
147#if BOOST_WORKAROUND(BOOST_GCC_VERSION,>=90300)&&\
148 BOOST_WORKAROUND(BOOST_GCC_VERSION,<100300)
149/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95888 */
150
151public:
152#else
153private:
154#endif
155
156 template<typename Iterator>
157 local_iterator_impl(
158 const_segment_map_iterator mapit,
159 Iterator it):
160 local_iterator_impl::iterator_adaptor_{BaseIterator(it)},
161 mapit{mapit}
162 {}
163
164public:
165 using base_iterator=BaseIterator;
166
167 local_iterator_impl()=default;
168 local_iterator_impl(const local_iterator_impl&)=default;
169 local_iterator_impl& operator=(const local_iterator_impl&)=default;
170
171 template<
172 typename BaseIterator2,
173 typename std::enable_if<
174 std::is_convertible<BaseIterator2,BaseIterator>::value
175 >::type* =nullptr
176 >
177 local_iterator_impl(
178 const local_iterator_impl<PolyCollection,BaseIterator2>& x):
179 local_iterator_impl::iterator_adaptor_{x.base()},
180 mapit{x.mapit}{}
181
182 template<
183 typename BaseIterator2,
184 typename std::enable_if<
185 !std::is_convertible<BaseIterator2,BaseIterator>::value&&
186 is_constructible<BaseIterator,BaseIterator2>::value
187 >::type* =nullptr
188 >
189 explicit local_iterator_impl(
190 const local_iterator_impl<PolyCollection,BaseIterator2>& x):
191 local_iterator_impl::iterator_adaptor_{BaseIterator(x.base())},
192 mapit{x.mapit}{}
193
194 template<
195 typename BaseIterator2,
196 typename std::enable_if<
197 !is_constructible<BaseIterator,BaseIterator2>::value&&
198 is_constructible<BaseIterator,segment_base_iterator>::value&&
199 is_constructible<BaseIterator2,segment_base_iterator>::value
200 >::type* =nullptr
201 >
202 explicit local_iterator_impl(
203 const local_iterator_impl<PolyCollection,BaseIterator2>& x):
204 local_iterator_impl::iterator_adaptor_{
205 base_iterator_from(x.segment(),x.base())},
206 mapit{x.mapit}{}
207
208 /* define [] to avoid Boost.Iterator operator_brackets_proxy mess */
209
210 template<typename DifferenceType>
211 typename std::iterator_traits<BaseIterator>::reference
212 operator[](DifferenceType n)const{return *(*this+n);}
213
214private:
215 template<typename,typename>
216 friend class local_iterator_impl;
217 friend PolyCollection;
218 template<typename>
219 friend struct iterator_traits;
220
221 template<typename BaseIterator2>
222 static BaseIterator base_iterator_from(
223 const segment_type& s,BaseIterator2 it)
224 {
225 segment_base_iterator bit=s.begin();
226 return BaseIterator{bit+(it-static_cast<BaseIterator2>(bit))};
227 }
228
229 base_iterator base()const noexcept
230 {return local_iterator_impl::iterator_adaptor_::base();}
231 const std::type_info& type_info()const{return *mapit->first;}
232 segment_type& segment()noexcept
233 {return const_cast<segment_type&>(mapit->second);}
234 const segment_type& segment()const noexcept{return mapit->second;}
235
236 const_segment_map_iterator mapit;
237};
238
239template<typename PolyCollection,typename BaseIterator>
240struct poly_collection_of<local_iterator_impl<PolyCollection,BaseIterator>>
241{
242 using type=PolyCollection;
243};
244
245} /* namespace poly_collection::detail */
246
247} /* namespace poly_collection */
248
249} /* namespace boost */
250
251#endif
252

source code of boost/libs/poly_collection/include/boost/poly_collection/detail/iterator_impl.hpp