File indexing completed on 2025-12-16 10:04:46
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_SEGMENT_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_SEGMENT_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <iterator>
0017 #include <memory>
0018 #include <type_traits>
0019 #include <utility>
0020
0021 namespace boost{
0022
0023 namespace poly_collection{
0024
0025 namespace detail{
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template<typename Model,typename Allocator>
0039 class segment
0040 {
0041 public:
0042 using value_type=typename Model::value_type;
0043 using allocator_type=Allocator;
0044 using base_iterator=typename Model::base_iterator;
0045 using const_base_iterator=typename Model::const_base_iterator;
0046 using base_sentinel=typename Model::base_sentinel;
0047 using const_base_sentinel=typename Model::const_base_sentinel;
0048 template<typename T>
0049 using iterator=typename Model::template iterator<T>;
0050 template<typename T>
0051 using const_iterator=typename Model::template const_iterator<T>;
0052
0053 template<typename T>
0054 static segment make(const allocator_type& al)
0055 {
0056 return segment_backend_implementation<T>::make(al);
0057 }
0058
0059
0060
0061 static segment make_from_prototype(const segment& x,const allocator_type& al)
0062 {
0063 return {from_prototype{},x,al};
0064 }
0065
0066 segment(const segment& x):
0067 pimpl{x.impl().copy()}{set_sentinel();}
0068 segment(segment&& x)=default;
0069 segment(const segment& x,const allocator_type& al):
0070 pimpl{x.impl().copy(al)}{set_sentinel();}
0071
0072
0073 segment(segment&& x,const allocator_type& al):
0074 pimpl{x.impl().move(al)}{set_sentinel();}
0075
0076 segment& operator=(const segment& x)
0077 {
0078 pimpl=allocator_traits::propagate_on_container_copy_assignment::value?
0079 x.impl().copy():x.impl().copy(impl().get_allocator());
0080 set_sentinel();
0081 return *this;
0082 }
0083
0084 segment& operator=(segment&& x)
0085 {
0086 pimpl=x.impl().move(
0087 allocator_traits::propagate_on_container_move_assignment::value?
0088 x.impl().get_allocator():impl().get_allocator());
0089 set_sentinel();
0090 return *this;
0091 }
0092
0093 friend bool operator==(const segment& x,const segment& y)
0094 {
0095 if(typeid(*(x.pimpl))!=typeid(*(y.pimpl)))return false;
0096 else return x.impl().equal(y.impl());
0097 }
0098
0099 friend bool operator!=(const segment& x,const segment& y){return !(x==y);}
0100
0101 base_iterator begin()const noexcept{return impl().begin();}
0102 template<typename U>
0103 base_iterator begin()const noexcept{return impl<U>().nv_begin();}
0104 base_iterator end()const noexcept{return impl().end();}
0105 template<typename U>
0106 base_iterator end()const noexcept{return impl<U>().nv_end();}
0107 base_sentinel sentinel()const noexcept{return snt;}
0108 bool empty()const noexcept{return impl().empty();}
0109 template<typename U>
0110 bool empty()const noexcept{return impl<U>().nv_empty();}
0111 std::size_t size()const noexcept{return impl().size();}
0112 template<typename U>
0113 std::size_t size()const noexcept{return impl<U>().nv_size();}
0114 std::size_t max_size()const noexcept{return impl().max_size();}
0115 template<typename U>
0116 std::size_t max_size()const noexcept
0117 {return impl<U>().nv_max_size();}
0118 void reserve(std::size_t n){filter(impl().reserve(n));}
0119 template<typename U>
0120 void reserve(std::size_t n){filter(impl<U>().nv_reserve(n));}
0121 std::size_t capacity()const noexcept{return impl().capacity();}
0122 template<typename U>
0123 std::size_t capacity()const noexcept
0124 {return impl<U>().nv_capacity();}
0125 void shrink_to_fit(){filter(impl().shrink_to_fit());}
0126 template<typename U>
0127 void shrink_to_fit(){filter(impl<U>().nv_shrink_to_fit());}
0128
0129 template<typename U,typename Iterator,typename... Args>
0130 base_iterator emplace(Iterator it,Args&&... args)
0131 {
0132 return filter(impl<U>().nv_emplace(it,std::forward<Args>(args)...));
0133 }
0134
0135 template<typename U,typename... Args>
0136 base_iterator emplace_back(Args&&... args)
0137 {
0138 return filter(impl<U>().nv_emplace_back(std::forward<Args>(args)...));
0139 }
0140
0141 template<typename T>
0142 base_iterator push_back(const T& x)
0143 {
0144 return filter(impl().push_back(subaddress(x)));
0145 }
0146
0147 template<
0148 typename T,
0149 typename std::enable_if<
0150 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
0151 >::type* =nullptr
0152 >
0153 base_iterator push_back(T&& x)
0154 {
0155 return filter(impl().push_back_move(subaddress(x)));
0156 }
0157
0158 template<typename U>
0159 base_iterator push_back_terminal(U&& x)
0160 {
0161 return filter(
0162 impl<typename std::decay<U>::type>().nv_push_back(std::forward<U>(x)));
0163 }
0164
0165 template<typename T>
0166 base_iterator insert(const_base_iterator it,const T& x)
0167 {
0168 return filter(impl().insert(it,subaddress(x)));
0169 }
0170
0171 template<typename U,typename T>
0172 base_iterator insert(const_iterator<U> it,const T& x)
0173 {
0174 return filter(
0175 impl<U>().nv_insert(it,*static_cast<const U*>(subaddress(x))));
0176 }
0177
0178 template<typename U,typename T>
0179 base_iterator insert(iterator<U> it,const T& x)
0180 {
0181 return insert(const_iterator<U>{it},x);
0182 }
0183
0184 template<
0185 typename T,
0186 typename std::enable_if<
0187 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
0188 >::type* =nullptr
0189 >
0190 base_iterator insert(const_base_iterator it,T&& x)
0191 {
0192 return filter(impl().insert_move(it,subaddress(x)));
0193 }
0194
0195 template<
0196 typename U,typename T,
0197 typename std::enable_if<
0198 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
0199 >::type* =nullptr
0200 >
0201 base_iterator insert(const_iterator<U> it,T&& x)
0202 {
0203 return filter(
0204 impl<U>().nv_insert(it,std::move(*static_cast<U*>(subaddress(x)))));
0205 }
0206
0207 template<
0208 typename U,typename T,
0209 typename std::enable_if<
0210 !std::is_lvalue_reference<T>::value&&!std::is_const<T>::value
0211 >::type* =nullptr
0212 >
0213 base_iterator insert(iterator<U> it,T&& x)
0214 {
0215 return insert(const_iterator<U>{it},std::move(x));
0216 }
0217
0218 template<typename InputIterator>
0219 base_iterator insert(InputIterator first,InputIterator last)
0220 {
0221 return filter(
0222 impl<typename std::iterator_traits<InputIterator>::value_type>().
0223 nv_insert(first,last));
0224 }
0225
0226 template<typename InputIterator>
0227 base_iterator insert(
0228 const_base_iterator it,InputIterator first,InputIterator last)
0229 {
0230 return insert(
0231 const_iterator<
0232 typename std::iterator_traits<InputIterator>::value_type>(it),
0233 first,last);
0234 }
0235
0236 template<typename U,typename InputIterator>
0237 base_iterator insert(
0238 const_iterator<U> it,InputIterator first,InputIterator last)
0239 {
0240 return filter(impl<U>().nv_insert(it,first,last));
0241 }
0242
0243 base_iterator erase(const_base_iterator it)
0244 {
0245 return filter(impl().erase(it));
0246 }
0247
0248 template<typename U>
0249 base_iterator erase(const_iterator<U> it)
0250 {
0251 return filter(impl<U>().nv_erase(it));
0252 }
0253
0254 base_iterator erase(const_base_iterator f,const_base_iterator l)
0255 {
0256 return filter(impl().erase(f,l));
0257 }
0258
0259 template<typename U>
0260 base_iterator erase(const_iterator<U> f,const_iterator<U> l)
0261 {
0262 return filter(impl<U>().nv_erase(f,l));
0263 }
0264
0265 template<typename Iterator>
0266 base_iterator erase_till_end(Iterator f)
0267 {
0268 return filter(impl().erase_till_end(f));
0269 }
0270
0271 template<typename Iterator>
0272 base_iterator erase_from_begin(Iterator l)
0273 {
0274 return filter(impl().erase_from_begin(l));
0275 }
0276
0277 void clear()noexcept{filter(impl().clear());}
0278 template<typename U>
0279 void clear()noexcept{filter(impl<U>().nv_clear());}
0280
0281 private:
0282 using allocator_traits=std::allocator_traits<Allocator>;
0283 using segment_backend=typename Model::template segment_backend<Allocator>;
0284 template<typename Concrete>
0285 using segment_backend_implementation=typename Model::
0286 template segment_backend_implementation<Concrete,Allocator>;
0287 using segment_backend_unique_ptr=
0288 typename segment_backend::segment_backend_unique_ptr;
0289 using range=typename segment_backend::range;
0290
0291 struct from_prototype{};
0292
0293 segment(segment_backend_unique_ptr&& pimpl):
0294 pimpl{std::move(pimpl)}{set_sentinel();}
0295 segment(from_prototype,const segment& x,const allocator_type& al):
0296 pimpl{x.impl().empty_copy(al)}{set_sentinel();}
0297
0298 segment_backend& impl()noexcept{return *pimpl;}
0299 const segment_backend& impl()const noexcept{return *pimpl;}
0300
0301 template<typename Concrete>
0302 segment_backend_implementation<Concrete>& impl()noexcept
0303 {
0304 return static_cast<segment_backend_implementation<Concrete>&>(impl());
0305 }
0306
0307 template<typename Concrete>
0308 const segment_backend_implementation<Concrete>& impl()const noexcept
0309 {
0310 return
0311 static_cast<const segment_backend_implementation<Concrete>&>(impl());
0312 }
0313
0314 template<typename T>
0315 static void* subaddress(T& x){return Model::subaddress(x);}
0316 template<typename T>
0317 static const void* subaddress(const T& x){return Model::subaddress(x);}
0318
0319 void set_sentinel(){filter(impl().end());}
0320 void filter(base_sentinel x){snt=x;}
0321 base_iterator filter(const range& x){snt=x.second;return x.first;}
0322
0323 segment_backend_unique_ptr pimpl;
0324 base_sentinel snt;
0325 };
0326
0327 }
0328
0329 }
0330
0331 }
0332
0333 #endif