]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/poly_collection/detail/segment.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / poly_collection / detail / segment.hpp
CommitLineData
92f5a8d4 1/* Copyright 2016-2018 Joaquin M Lopez Munoz.
b32b8144
FG
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
21namespace boost{
22
23namespace poly_collection{
24
25namespace 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
38template<typename Model,typename Allocator>
39class segment
40{
41public:
42 using value_type=typename Model::value_type;
92f5a8d4 43 using allocator_type=Allocator; /* needed for uses-allocator construction */
b32b8144
FG
44 using base_iterator=typename Model::base_iterator;
45 using const_base_iterator=typename Model::const_base_iterator;
46 using base_sentinel=typename Model::base_sentinel;
47 using const_base_sentinel=typename Model::const_base_sentinel;
48 template<typename T>
49 using iterator=typename Model::template iterator<T>;
50 template<typename T>
51 using const_iterator=typename Model::template const_iterator<T>;
52
53 template<typename T>
92f5a8d4 54 static segment make(const allocator_type& al)
b32b8144 55 {
92f5a8d4 56 return segment_backend_implementation<T>::make(al);
b32b8144
FG
57 }
58
59 /* clones the implementation of x with no elements */
60
92f5a8d4 61 static segment make_from_prototype(const segment& x,const allocator_type& al)
b32b8144 62 {
92f5a8d4 63 return {from_prototype{},x,al};
b32b8144
FG
64 }
65
92f5a8d4
TL
66 segment(const segment& x):
67 pimpl{x.impl().copy()}{set_sentinel();}
b32b8144 68 segment(segment&& x)=default;
92f5a8d4
TL
69 segment(const segment& x,const allocator_type& al):
70 pimpl{x.impl().copy(al)}{set_sentinel();}
71
72 /* TODO: try ptr-level move before impl().move() */
73 segment(segment&& x,const allocator_type& al):
74 pimpl{x.impl().move(al)}{set_sentinel();}
75
76 segment& operator=(const segment& x)
77 {
78 pimpl=allocator_traits::propagate_on_container_copy_assignment::value?
79 x.impl().copy():x.impl().copy(impl().get_allocator());
80 set_sentinel();
81 return *this;
82 }
83
84 segment& operator=(segment&& x)
b32b8144 85 {
92f5a8d4
TL
86 pimpl=x.impl().move(
87 allocator_traits::propagate_on_container_move_assignment::value?
88 x.impl().get_allocator():impl().get_allocator());
89 set_sentinel();
b32b8144
FG
90 return *this;
91 }
92
93 friend bool operator==(const segment& x,const segment& y)
94 {
95 if(typeid(*(x.pimpl))!=typeid(*(y.pimpl)))return false;
96 else return x.impl().equal(y.impl());
97 }
98
99 friend bool operator!=(const segment& x,const segment& y){return !(x==y);}
100
101 base_iterator begin()const noexcept{return impl().begin();}
102 template<typename U>
103 base_iterator begin()const noexcept{return impl<U>().nv_begin();}
104 base_iterator end()const noexcept{return impl().end();}
105 template<typename U>
106 base_iterator end()const noexcept{return impl<U>().nv_end();}
107 base_sentinel sentinel()const noexcept{return snt;}
108 bool empty()const noexcept{return impl().empty();}
109 template<typename U>
110 bool empty()const noexcept{return impl<U>().nv_empty();}
111 std::size_t size()const noexcept{return impl().size();}
112 template<typename U>
113 std::size_t size()const noexcept{return impl<U>().nv_size();}
114 std::size_t max_size()const noexcept{return impl().max_size();}
115 template<typename U>
116 std::size_t max_size()const noexcept
117 {return impl<U>().nv_max_size();}
118 void reserve(std::size_t n){filter(impl().reserve(n));}
119 template<typename U>
120 void reserve(std::size_t n){filter(impl<U>().nv_reserve(n));}
121 std::size_t capacity()const noexcept{return impl().capacity();}
122 template<typename U>
123 std::size_t capacity()const noexcept
124 {return impl<U>().nv_capacity();}
125 void shrink_to_fit(){filter(impl().shrink_to_fit());}
126 template<typename U>
127 void shrink_to_fit(){filter(impl<U>().nv_shrink_to_fit());}
128
129 template<typename U,typename Iterator,typename... Args>
130 base_iterator emplace(Iterator it,Args&&... args)
131 {
132 return filter(impl<U>().nv_emplace(it,std::forward<Args>(args)...));
133 }
134
135 template<typename U,typename... Args>
136 base_iterator emplace_back(Args&&... args)
137 {
138 return filter(impl<U>().nv_emplace_back(std::forward<Args>(args)...));
139 }
140
141 template<typename T>
142 base_iterator push_back(const T& x)
143 {
144 return filter(impl().push_back(subaddress(x)));
145 }
146
147 template<
148 typename T,
149 typename std::enable_if<
150 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
151 >::type* =nullptr
152 >
153 base_iterator push_back(T&& x)
154 {
155 return filter(impl().push_back_move(subaddress(x)));
156 }
157
158 template<typename U>
159 base_iterator push_back_terminal(U&& x)
160 {
161 return filter(
162 impl<typename std::decay<U>::type>().nv_push_back(std::forward<U>(x)));
163 }
164
165 template<typename T>
166 base_iterator insert(const_base_iterator it,const T& x)
167 {
168 return filter(impl().insert(it,subaddress(x)));
169 }
170
171 template<typename U,typename T>
172 base_iterator insert(const_iterator<U> it,const T& x)
173 {
174 return filter(
175 impl<U>().nv_insert(it,*static_cast<const U*>(subaddress(x))));
176 }
177
178 template<
179 typename T,
180 typename std::enable_if<
181 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
182 >::type* =nullptr
183 >
184 base_iterator insert(const_base_iterator it,T&& x)
185 {
186 return filter(impl().insert_move(it,subaddress(x)));
187 }
188
189 template<
190 typename U,typename T,
191 typename std::enable_if<
192 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
193 >::type* =nullptr
194 >
195 base_iterator insert(const_iterator<U> it,T&& x)
196 {
197 return filter(
198 impl<U>().nv_insert(it,std::move(*static_cast<U*>(subaddress(x)))));
199 }
200
201 template<typename InputIterator>
202 base_iterator insert(InputIterator first,InputIterator last)
203 {
204 return filter(
205 impl<typename std::iterator_traits<InputIterator>::value_type>().
206 nv_insert(first,last));
207 }
208
209 template<typename InputIterator>
210 base_iterator insert(
211 const_base_iterator it,InputIterator first,InputIterator last)
212 {
213 return insert(
214 const_iterator<
215 typename std::iterator_traits<InputIterator>::value_type>(it),
216 first,last);
217 }
218
219 template<typename U,typename InputIterator>
220 base_iterator insert(
221 const_iterator<U> it,InputIterator first,InputIterator last)
222 {
223 return filter(impl<U>().nv_insert(it,first,last));
224 }
225
226 base_iterator erase(const_base_iterator it)
227 {
228 return filter(impl().erase(it));
229 }
230
231 template<typename U>
232 base_iterator erase(const_iterator<U> it)
233 {
234 return filter(impl<U>().nv_erase(it));
235 }
236
237 base_iterator erase(const_base_iterator f,const_base_iterator l)
238 {
239 return filter(impl().erase(f,l));
240 }
241
242 template<typename U>
243 base_iterator erase(const_iterator<U> f,const_iterator<U> l)
244 {
245 return filter(impl<U>().nv_erase(f,l));
246 }
247
248 template<typename Iterator>
249 base_iterator erase_till_end(Iterator f)
250 {
251 return filter(impl().erase_till_end(f));
252 }
253
254 template<typename Iterator>
255 base_iterator erase_from_begin(Iterator l)
256 {
257 return filter(impl().erase_from_begin(l));
258 }
259
260 void clear()noexcept{filter(impl().clear());}
261 template<typename U>
262 void clear()noexcept{filter(impl<U>().nv_clear());}
263
264private:
92f5a8d4
TL
265 using allocator_traits=std::allocator_traits<Allocator>;
266 using segment_backend=typename Model::template segment_backend<Allocator>;
b32b8144
FG
267 template<typename Concrete>
268 using segment_backend_implementation=typename Model::
269 template segment_backend_implementation<Concrete,Allocator>;
270 using segment_backend_unique_ptr=
271 typename segment_backend::segment_backend_unique_ptr;
272 using range=typename segment_backend::range;
273
274 struct from_prototype{};
275
276 segment(segment_backend_unique_ptr&& pimpl):
277 pimpl{std::move(pimpl)}{set_sentinel();}
92f5a8d4
TL
278 segment(from_prototype,const segment& x,const allocator_type& al):
279 pimpl{x.impl().empty_copy(al)}{set_sentinel();}
b32b8144
FG
280
281 segment_backend& impl()noexcept{return *pimpl;}
282 const segment_backend& impl()const noexcept{return *pimpl;}
283
284 template<typename Concrete>
285 segment_backend_implementation<Concrete>& impl()noexcept
286 {
287 return static_cast<segment_backend_implementation<Concrete>&>(impl());
288 }
289
290 template<typename Concrete>
291 const segment_backend_implementation<Concrete>& impl()const noexcept
292 {
293 return
294 static_cast<const segment_backend_implementation<Concrete>&>(impl());
295 }
296
297 template<typename T>
298 static void* subaddress(T& x){return Model::subaddress(x);}
299 template<typename T>
300 static const void* subaddress(const T& x){return Model::subaddress(x);}
301
302 void set_sentinel(){filter(impl().end());}
303 void filter(base_sentinel x){snt=x;}
304 base_iterator filter(const range& x){snt=x.second;return x.first;}
305
306 segment_backend_unique_ptr pimpl;
307 base_sentinel snt;
308};
309
310} /* namespace poly_collection::detail */
311
312} /* namespace poly_collection */
313
314} /* namespace boost */
315
316#endif