]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/poly_collection/detail/segment.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / poly_collection / detail / segment.hpp
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)
5 *
6 * See http://www.boost.org/libs/poly_collection for library home page.
7 */
8
9 #ifndef BOOST_POLY_COLLECTION_DETAIL_SEGMENT_HPP
10 #define BOOST_POLY_COLLECTION_DETAIL_SEGMENT_HPP
11
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15
16 #include <iterator>
17 #include <memory>
18 #include <type_traits>
19 #include <utility>
20
21 namespace boost{
22
23 namespace poly_collection{
24
25 namespace detail{
26
27 /* segment<Model,Allocator> encapsulates implementations of
28 * Model::segment_backend virtual interface under a value-semantics type for
29 * use by poly_collection. The techique is described by Sean Parent at slides
30 * 157-205 of
31 * https://github.com/sean-parent/sean-parent.github.com/wiki/
32 * presentations/2013-09-11-cpp-seasoning/cpp-seasoning.pdf
33 * with one twist: when the type of the implementation can be known at compile
34 * time, a downcast is done and non-virtual member functions (named with a nv_
35 * prefix) are used: this increases the performance of some operations.
36 */
37
38 template<typename Model,typename Allocator>
39 class segment
40 {
41 public:
42 using value_type=typename Model::value_type;
43 using base_iterator=typename Model::base_iterator;
44 using const_base_iterator=typename Model::const_base_iterator;
45 using base_sentinel=typename Model::base_sentinel;
46 using const_base_sentinel=typename Model::const_base_sentinel;
47 template<typename T>
48 using iterator=typename Model::template iterator<T>;
49 template<typename T>
50 using const_iterator=typename Model::template const_iterator<T>;
51
52 template<typename T>
53 static segment make(const Allocator& al)
54 {
55 return Model::template make<T>(al);
56 }
57
58 /* clones the implementation of x with no elements */
59
60 static segment make_from_prototype(const segment& x)
61 {
62 return {from_prototype{},x};
63 }
64
65 segment(const segment& x):pimpl{x.impl().copy()}{set_sentinel();}
66 segment(segment&& x)=default;
67 segment& operator=(segment x) // TODO: Why do we need this?
68 {
69 pimpl=std::move(x.pimpl);
70 snt=x.snt;
71 return *this;
72 }
73
74 friend bool operator==(const segment& x,const segment& y)
75 {
76 if(typeid(*(x.pimpl))!=typeid(*(y.pimpl)))return false;
77 else return x.impl().equal(y.impl());
78 }
79
80 friend bool operator!=(const segment& x,const segment& y){return !(x==y);}
81
82 base_iterator begin()const noexcept{return impl().begin();}
83 template<typename U>
84 base_iterator begin()const noexcept{return impl<U>().nv_begin();}
85 base_iterator end()const noexcept{return impl().end();}
86 template<typename U>
87 base_iterator end()const noexcept{return impl<U>().nv_end();}
88 base_sentinel sentinel()const noexcept{return snt;}
89 bool empty()const noexcept{return impl().empty();}
90 template<typename U>
91 bool empty()const noexcept{return impl<U>().nv_empty();}
92 std::size_t size()const noexcept{return impl().size();}
93 template<typename U>
94 std::size_t size()const noexcept{return impl<U>().nv_size();}
95 std::size_t max_size()const noexcept{return impl().max_size();}
96 template<typename U>
97 std::size_t max_size()const noexcept
98 {return impl<U>().nv_max_size();}
99 void reserve(std::size_t n){filter(impl().reserve(n));}
100 template<typename U>
101 void reserve(std::size_t n){filter(impl<U>().nv_reserve(n));}
102 std::size_t capacity()const noexcept{return impl().capacity();}
103 template<typename U>
104 std::size_t capacity()const noexcept
105 {return impl<U>().nv_capacity();}
106 void shrink_to_fit(){filter(impl().shrink_to_fit());}
107 template<typename U>
108 void shrink_to_fit(){filter(impl<U>().nv_shrink_to_fit());}
109
110 template<typename U,typename Iterator,typename... Args>
111 base_iterator emplace(Iterator it,Args&&... args)
112 {
113 return filter(impl<U>().nv_emplace(it,std::forward<Args>(args)...));
114 }
115
116 template<typename U,typename... Args>
117 base_iterator emplace_back(Args&&... args)
118 {
119 return filter(impl<U>().nv_emplace_back(std::forward<Args>(args)...));
120 }
121
122 template<typename T>
123 base_iterator push_back(const T& x)
124 {
125 return filter(impl().push_back(subaddress(x)));
126 }
127
128 template<
129 typename T,
130 typename std::enable_if<
131 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
132 >::type* =nullptr
133 >
134 base_iterator push_back(T&& x)
135 {
136 return filter(impl().push_back_move(subaddress(x)));
137 }
138
139 template<typename U>
140 base_iterator push_back_terminal(U&& x)
141 {
142 return filter(
143 impl<typename std::decay<U>::type>().nv_push_back(std::forward<U>(x)));
144 }
145
146 template<typename T>
147 base_iterator insert(const_base_iterator it,const T& x)
148 {
149 return filter(impl().insert(it,subaddress(x)));
150 }
151
152 template<typename U,typename T>
153 base_iterator insert(const_iterator<U> it,const T& x)
154 {
155 return filter(
156 impl<U>().nv_insert(it,*static_cast<const U*>(subaddress(x))));
157 }
158
159 template<
160 typename T,
161 typename std::enable_if<
162 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
163 >::type* =nullptr
164 >
165 base_iterator insert(const_base_iterator it,T&& x)
166 {
167 return filter(impl().insert_move(it,subaddress(x)));
168 }
169
170 template<
171 typename U,typename T,
172 typename std::enable_if<
173 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
174 >::type* =nullptr
175 >
176 base_iterator insert(const_iterator<U> it,T&& x)
177 {
178 return filter(
179 impl<U>().nv_insert(it,std::move(*static_cast<U*>(subaddress(x)))));
180 }
181
182 template<typename InputIterator>
183 base_iterator insert(InputIterator first,InputIterator last)
184 {
185 return filter(
186 impl<typename std::iterator_traits<InputIterator>::value_type>().
187 nv_insert(first,last));
188 }
189
190 template<typename InputIterator>
191 base_iterator insert(
192 const_base_iterator it,InputIterator first,InputIterator last)
193 {
194 return insert(
195 const_iterator<
196 typename std::iterator_traits<InputIterator>::value_type>(it),
197 first,last);
198 }
199
200 template<typename U,typename InputIterator>
201 base_iterator insert(
202 const_iterator<U> it,InputIterator first,InputIterator last)
203 {
204 return filter(impl<U>().nv_insert(it,first,last));
205 }
206
207 base_iterator erase(const_base_iterator it)
208 {
209 return filter(impl().erase(it));
210 }
211
212 template<typename U>
213 base_iterator erase(const_iterator<U> it)
214 {
215 return filter(impl<U>().nv_erase(it));
216 }
217
218 base_iterator erase(const_base_iterator f,const_base_iterator l)
219 {
220 return filter(impl().erase(f,l));
221 }
222
223 template<typename U>
224 base_iterator erase(const_iterator<U> f,const_iterator<U> l)
225 {
226 return filter(impl<U>().nv_erase(f,l));
227 }
228
229 template<typename Iterator>
230 base_iterator erase_till_end(Iterator f)
231 {
232 return filter(impl().erase_till_end(f));
233 }
234
235 template<typename Iterator>
236 base_iterator erase_from_begin(Iterator l)
237 {
238 return filter(impl().erase_from_begin(l));
239 }
240
241 void clear()noexcept{filter(impl().clear());}
242 template<typename U>
243 void clear()noexcept{filter(impl<U>().nv_clear());}
244
245 private:
246 using segment_backend=typename Model::segment_backend;
247 template<typename Concrete>
248 using segment_backend_implementation=typename Model::
249 template segment_backend_implementation<Concrete,Allocator>;
250 using segment_backend_unique_ptr=
251 typename segment_backend::segment_backend_unique_ptr;
252 using range=typename segment_backend::range;
253
254 struct from_prototype{};
255
256 segment(segment_backend_unique_ptr&& pimpl):
257 pimpl{std::move(pimpl)}{set_sentinel();}
258 segment(from_prototype,const segment& x):
259 pimpl{x.impl().empty_copy()}{set_sentinel();}
260
261 segment_backend& impl()noexcept{return *pimpl;}
262 const segment_backend& impl()const noexcept{return *pimpl;}
263
264 template<typename Concrete>
265 segment_backend_implementation<Concrete>& impl()noexcept
266 {
267 return static_cast<segment_backend_implementation<Concrete>&>(impl());
268 }
269
270 template<typename Concrete>
271 const segment_backend_implementation<Concrete>& impl()const noexcept
272 {
273 return
274 static_cast<const segment_backend_implementation<Concrete>&>(impl());
275 }
276
277 template<typename T>
278 static void* subaddress(T& x){return Model::subaddress(x);}
279 template<typename T>
280 static const void* subaddress(const T& x){return Model::subaddress(x);}
281
282 void set_sentinel(){filter(impl().end());}
283 void filter(base_sentinel x){snt=x;}
284 base_iterator filter(const range& x){snt=x.second;return x.first;}
285
286 segment_backend_unique_ptr pimpl;
287 base_sentinel snt;
288 };
289
290 } /* namespace poly_collection::detail */
291
292 } /* namespace poly_collection */
293
294 } /* namespace boost */
295
296 #endif