]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/container/detail/node_alloc_holder.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / container / detail / node_alloc_holder.hpp
CommitLineData
7c673cae
FG
1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/container for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10
11#ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
12#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
13
14#ifndef BOOST_CONFIG_HPP
15# include <boost/config.hpp>
16#endif
17
18#if defined(BOOST_HAS_PRAGMA_ONCE)
19# pragma once
20#endif
21
22#include <boost/container/detail/config_begin.hpp>
23#include <boost/container/detail/workaround.hpp>
24
25// container
26#include <boost/container/allocator_traits.hpp>
27// container/detail
28#include <boost/container/detail/addressof.hpp>
29#include <boost/container/detail/alloc_helpers.hpp>
30#include <boost/container/detail/allocator_version_traits.hpp>
31#include <boost/container/detail/construct_in_place.hpp>
32#include <boost/container/detail/destroyers.hpp>
b32b8144 33#include <boost/move/detail/iterator_to_raw_pointer.hpp>
7c673cae
FG
34#include <boost/container/detail/mpl.hpp>
35#include <boost/container/detail/placement_new.hpp>
b32b8144 36#include <boost/move/detail/to_raw_pointer.hpp>
7c673cae
FG
37#include <boost/container/detail/type_traits.hpp>
38#include <boost/container/detail/version_type.hpp>
1e59de90 39#include <boost/container/detail/is_pair.hpp>
7c673cae
FG
40// intrusive
41#include <boost/intrusive/detail/mpl.hpp>
42#include <boost/intrusive/options.hpp>
43// move
44#include <boost/move/utility_core.hpp>
45#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
46#include <boost/move/detail/fwd_macros.hpp>
47#endif
48// other
49#include <boost/core/no_exceptions_support.hpp>
50
51
52namespace boost {
53namespace container {
1e59de90
TL
54
55//This trait is used to type-pun std::pair because in C++03
56//compilers std::pair is useless for C++11 features
57template<class T, bool = dtl::is_pair<T>::value >
58struct node_internal_data_type
59{
60 typedef T type;
61};
62
63template<class T>
64struct node_internal_data_type< T, true>
65{
66 typedef dtl::pair< typename dtl::remove_const<typename T::first_type>::type
67 , typename T::second_type>
68 type;
69};
70
71template <class T, class HookDefiner>
72struct base_node
73 : public HookDefiner::type
74{
75 public:
76 typedef T value_type;
77 typedef typename node_internal_data_type<T>::type internal_type;
78 typedef typename HookDefiner::type hook_type;
79
80 typedef typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type storage_t;
81 storage_t m_storage;
82
83 #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000)
84 #pragma GCC diagnostic push
85 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
86 #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING
87 # endif
88 public:
89
90 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
91
92 template<class Alloc, class ...Args>
93 explicit base_node(Alloc &a, Args &&...args)
94 : hook_type()
95 {
96 ::boost::container::allocator_traits<Alloc>::construct
97 (a, &this->get_real_data(), ::boost::forward<Args>(args)...);
98 }
99
100 #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
101
102 #define BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL(N) \
103 template< class Alloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
104 explicit base_node(Alloc &a BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
105 : hook_type()\
106 {\
107 ::boost::container::allocator_traits<Alloc>::construct\
108 (a, &this->get_real_data() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
109 }\
110 //
111 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL)
112 #undef BOOST_CONTAINER_BASE_NODE_CONSTRUCT_IMPL
113
114 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
115
116 template<class Alloc, class It>
117 explicit base_node(iterator_arg_t, Alloc &a, It it)
118 : hook_type()
119 {
120 ::boost::container::construct_in_place(a, &this->get_real_data(), it);
121 }
122
123 BOOST_CONTAINER_FORCEINLINE T &get_data()
124 { return *move_detail::force_ptr<T*>(this->m_storage.data); }
125
126 BOOST_CONTAINER_FORCEINLINE const T &get_data() const
127 { return *move_detail::force_ptr<const T*>(this->m_storage.data); }
128
129 BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data()
130 { return *move_detail::force_ptr<internal_type*>(this->m_storage.data); }
131
132 BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const
133 { return *move_detail::force_ptr<const internal_type*>(this->m_storage.data); }
134
135 #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING)
136 #pragma GCC diagnostic pop
137 #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING
138 # endif
139
140 template<class Alloc>
141 void destructor(Alloc &a) BOOST_NOEXCEPT
142 {
143 allocator_traits<Alloc>::destroy
144 (a, &this->get_real_data());
145 this->~base_node();
146 }
147
148 template<class Pair>
149 BOOST_CONTAINER_FORCEINLINE
150 typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
151 do_assign(const Pair &p)
152 {
153 typedef typename Pair::first_type first_type;
154 const_cast<typename dtl::remove_const<first_type>::type &>(this->get_real_data().first) = p.first;
155 this->get_real_data().second = p.second;
156 }
157
158 template<class V>
159 BOOST_CONTAINER_FORCEINLINE
160 typename dtl::disable_if< dtl::is_pair<V>, void >::type
161 do_assign(const V &v)
162 { this->get_real_data() = v; }
163
164 template<class Pair>
165 BOOST_CONTAINER_FORCEINLINE
166 typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
167 do_move_assign(Pair &p)
168 {
169 typedef typename Pair::first_type first_type;
170 const_cast<first_type&>(this->get_real_data().first) = ::boost::move(p.first);
171 this->get_real_data().second = ::boost::move(p.second);
172 }
173
174 template<class V>
175 BOOST_CONTAINER_FORCEINLINE
176 typename dtl::disable_if< dtl::is_pair<V>, void >::type
177 do_move_assign(V &v)
178 { this->get_real_data() = ::boost::move(v); }
179
180 private:
181 base_node();
182
183 BOOST_CONTAINER_FORCEINLINE ~base_node()
184 { }
185};
186
187
11fdf7f2 188namespace dtl {
7c673cae 189
92f5a8d4
TL
190BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_compare)
191BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(key_equal)
192BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(hasher)
7c673cae
FG
193BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type)
194
195template<class Allocator, class ICont>
196struct node_alloc_holder
92f5a8d4
TL
197 : public allocator_traits<Allocator>::template
198 portable_rebind_alloc<typename ICont::value_type>::type //NodeAlloc
7c673cae
FG
199{
200 //If the intrusive container is an associative container, obtain the predicate, which will
92f5a8d4 201 //be of type node_compare<>. If not an associative container val_compare will be a "nat" type.
7c673cae 202 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
11fdf7f2 203 ( boost::container::dtl::
92f5a8d4 204 , ICont, key_compare, dtl::nat) intrusive_val_compare;
7c673cae 205 //In that case obtain the value predicate from the node predicate via predicate_type
92f5a8d4 206 //if intrusive_val_compare is node_compare<>, nat otherwise
7c673cae 207 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
11fdf7f2 208 ( boost::container::dtl::
92f5a8d4
TL
209 , intrusive_val_compare
210 , predicate_type, dtl::nat) val_compare;
211
212 //If the intrusive container is a hash container, obtain the predicate, which will
213 //be of type node_compare<>. If not an associative container val_equal will be a "nat" type.
214 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
215 (boost::container::dtl::
216 , ICont, key_equal, dtl::nat2) intrusive_val_equal;
217 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
218 (boost::container::dtl::
219 , ICont, hasher, dtl::nat3) intrusive_val_hasher;
220 //In that case obtain the value predicate from the node predicate via predicate_type
221 //if intrusive_val_compare is node_compare<>, nat otherwise
222 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
223 (boost::container::dtl::
224 , intrusive_val_equal
225 , predicate_type, dtl::nat2) val_equal;
226 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
227 (boost::container::dtl::
228 , intrusive_val_hasher
229 , predicate_type, dtl::nat3) val_hasher;
7c673cae
FG
230
231 typedef allocator_traits<Allocator> allocator_traits_type;
92f5a8d4 232 typedef typename allocator_traits_type::value_type val_type;
7c673cae
FG
233 typedef ICont intrusive_container;
234 typedef typename ICont::value_type Node;
235 typedef typename allocator_traits_type::template
236 portable_rebind_alloc<Node>::type NodeAlloc;
237 typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
11fdf7f2 238 typedef dtl::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
7c673cae
FG
239 typedef Allocator ValAlloc;
240 typedef typename node_allocator_traits_type::pointer NodePtr;
11fdf7f2 241 typedef dtl::scoped_deallocator<NodeAlloc> Deallocator;
7c673cae
FG
242 typedef typename node_allocator_traits_type::size_type size_type;
243 typedef typename node_allocator_traits_type::difference_type difference_type;
11fdf7f2
TL
244 typedef dtl::integral_constant<unsigned,
245 boost::container::dtl::
7c673cae
FG
246 version<NodeAlloc>::value> alloc_version;
247 typedef typename ICont::iterator icont_iterator;
248 typedef typename ICont::const_iterator icont_citerator;
1e59de90 249 typedef allocator_node_destroyer<NodeAlloc> Destroyer;
7c673cae
FG
250 typedef allocator_traits<NodeAlloc> NodeAllocTraits;
251 typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
252
253 private:
254 BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
255
256 public:
257
258 //Constructors for sequence containers
259 node_alloc_holder()
7c673cae
FG
260 {}
261
262 explicit node_alloc_holder(const ValAlloc &a)
92f5a8d4 263 : NodeAlloc(a)
7c673cae
FG
264 {}
265
b32b8144 266 //Constructors for associative containers
92f5a8d4
TL
267 node_alloc_holder(const val_compare &c, const ValAlloc &a)
268 : NodeAlloc(a), m_icont(typename ICont::key_compare(c))
269 {}
270
271 node_alloc_holder(const val_hasher &hf, const val_equal &eql, const ValAlloc &a)
272 : NodeAlloc(a)
273 , m_icont(typename ICont::bucket_traits()
274 , typename ICont::hasher(hf)
275 , typename ICont::key_equal(eql))
276 {}
277
278 node_alloc_holder(const val_hasher &hf, const ValAlloc &a)
279 : NodeAlloc(a)
280 , m_icont(typename ICont::bucket_traits()
281 , typename ICont::hasher(hf)
282 , typename ICont::key_equal())
283 {}
284
285 node_alloc_holder(const val_hasher &hf)
286 : m_icont(typename ICont::bucket_traits()
287 , typename ICont::hasher(hf)
288 , typename ICont::key_equal())
b32b8144
FG
289 {}
290
7c673cae 291 explicit node_alloc_holder(const node_alloc_holder &x)
92f5a8d4 292 : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
7c673cae
FG
293 {}
294
92f5a8d4
TL
295 node_alloc_holder(const node_alloc_holder &x, const val_compare &c)
296 : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
297 , m_icont(typename ICont::key_compare(c))
298 {}
299
300 node_alloc_holder(const node_alloc_holder &x, const val_hasher &hf, const val_equal &eql)
301 : NodeAlloc(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
302 , m_icont( typename ICont::bucket_traits()
303 , typename ICont::hasher(hf)
304 , typename ICont::key_equal(eql))
305 {}
306
307 node_alloc_holder(const val_hasher &hf, const val_equal &eql)
308 : m_icont(typename ICont::bucket_traits()
309 , typename ICont::hasher(hf)
310 , typename ICont::key_equal(eql))
b32b8144
FG
311 {}
312
7c673cae 313 explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
1e59de90 314 : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc()))
7c673cae
FG
315 { this->icont().swap(x.icont()); }
316
92f5a8d4
TL
317 explicit node_alloc_holder(const val_compare &c)
318 : m_icont(typename ICont::key_compare(c))
7c673cae
FG
319 {}
320
321 //helpers for move assignments
92f5a8d4 322 explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_compare &c)
1e59de90 323 : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc())), m_icont(typename ICont::key_compare(c))
7c673cae
FG
324 { this->icont().swap(x.icont()); }
325
92f5a8d4 326 explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const val_hasher &hf, const val_equal &eql)
1e59de90 327 : NodeAlloc(boost::move(BOOST_MOVE_TO_LV(x).node_alloc()))
92f5a8d4
TL
328 , m_icont( typename ICont::bucket_traits()
329 , typename ICont::hasher(hf)
330 , typename ICont::key_equal(eql))
1e59de90 331 { this->icont().swap(BOOST_MOVE_TO_LV(x).icont()); }
92f5a8d4 332
7c673cae
FG
333 void copy_assign_alloc(const node_alloc_holder &x)
334 {
11fdf7f2 335 dtl::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
92f5a8d4
TL
336 dtl::assign_alloc( static_cast<NodeAlloc &>(*this)
337 , static_cast<const NodeAlloc &>(x), flag);
7c673cae
FG
338 }
339
340 void move_assign_alloc( node_alloc_holder &x)
341 {
11fdf7f2 342 dtl::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
92f5a8d4
TL
343 dtl::move_alloc( static_cast<NodeAlloc &>(*this)
344 , static_cast<NodeAlloc &>(x), flag);
7c673cae
FG
345 }
346
347 ~node_alloc_holder()
348 { this->clear(alloc_version()); }
349
350 size_type max_size() const
351 { return allocator_traits_type::max_size(this->node_alloc()); }
352
353 NodePtr allocate_one()
354 { return AllocVersionTraits::allocate_one(this->node_alloc()); }
355
356 void deallocate_one(const NodePtr &p)
357 { AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
358
359 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
360
361 template<class ...Args>
362 NodePtr create_node(Args &&...args)
363 {
364 NodePtr p = this->allocate_one();
1e59de90
TL
365 NodeAlloc &nalloc = this->node_alloc();
366 Deallocator node_deallocator(p, nalloc);
367 ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
368 Node(nalloc, boost::forward<Args>(args)...);
369 node_deallocator.release();
7c673cae
FG
370 return (p);
371 }
372
373 #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
374
375 #define BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL(N) \
376 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
377 NodePtr create_node(BOOST_MOVE_UREF##N)\
378 {\
379 NodePtr p = this->allocate_one();\
1e59de90
TL
380 NodeAlloc &nalloc = this->node_alloc();\
381 Deallocator node_deallocator(p, nalloc);\
382 ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())\
383 Node(nalloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
384 node_deallocator.release();\
7c673cae
FG
385 return (p);\
386 }\
387 //
388 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL)
389 #undef BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL
390
391 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
392
393 template<class It>
394 NodePtr create_node_from_it(const It &it)
395 {
396 NodePtr p = this->allocate_one();
1e59de90
TL
397 NodeAlloc &nalloc = this->node_alloc();
398 Deallocator node_deallocator(p, nalloc);
399 ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
400 Node(iterator_arg_t(), nalloc, it);
401 node_deallocator.release();
7c673cae
FG
402 return (p);
403 }
404
405 template<class KeyConvertible>
406 NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
407 {
408 NodePtr p = this->allocate_one();
7c673cae 409 BOOST_TRY{
92f5a8d4
TL
410 ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;
411 NodeAlloc &na = this->node_alloc();
412 node_allocator_traits_type::construct
413 (na, dtl::addressof(p->get_real_data().first), boost::forward<KeyConvertible>(key));
414 BOOST_TRY{
415 node_allocator_traits_type::construct(na, dtl::addressof(p->get_real_data().second));
416 }
417 BOOST_CATCH(...){
418 node_allocator_traits_type::destroy(na, dtl::addressof(p->get_real_data().first));
419 BOOST_RETHROW;
420 }
421 BOOST_CATCH_END
7c673cae 422 }
92f5a8d4
TL
423 BOOST_CATCH(...) {
424 p->destroy_header();
425 this->node_alloc().deallocate(p, 1);
426 BOOST_RETHROW
7c673cae
FG
427 }
428 BOOST_CATCH_END
7c673cae
FG
429 return (p);
430 }
431
432 void destroy_node(const NodePtr &nodep)
433 {
1e59de90 434 boost::movelib::to_raw_pointer(nodep)->destructor(this->node_alloc());
7c673cae
FG
435 this->deallocate_one(nodep);
436 }
437
438 void swap(node_alloc_holder &x)
439 {
440 this->icont().swap(x.icont());
11fdf7f2
TL
441 dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
442 dtl::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
7c673cae
FG
443 }
444
445 template<class FwdIterator, class Inserter>
446 void allocate_many_and_construct
1e59de90 447 (FwdIterator beg, size_type n, Inserter inserter)
7c673cae
FG
448 {
449 if(n){
92f5a8d4 450 typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain_t;
7c673cae
FG
451
452 //Try to allocate memory in a single block
92f5a8d4
TL
453 typedef typename multiallocation_chain_t::iterator multialloc_iterator_t;
454 multiallocation_chain_t chain;
7c673cae 455 NodeAlloc &nalloc = this->node_alloc();
92f5a8d4
TL
456 node_allocator_version_traits_type::allocate_individual(nalloc, n, chain);
457 multialloc_iterator_t itbeg = chain.begin();
458 multialloc_iterator_t itlast = chain.last();
459 chain.clear();
460
7c673cae 461 Node *p = 0;
92f5a8d4 462 BOOST_TRY{
7c673cae 463 Deallocator node_deallocator(NodePtr(), nalloc);
1e59de90 464 dtl::scoped_node_destructor<NodeAlloc> sdestructor(nalloc, 0);
92f5a8d4
TL
465 while(n){
466 --n;
b32b8144 467 p = boost::movelib::iterator_to_raw_pointer(itbeg);
92f5a8d4
TL
468 ++itbeg; //Increment iterator before overwriting pointed memory
469 //This does not throw
1e59de90
TL
470 ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t())
471 Node(iterator_arg_t(), nalloc, beg);
7c673cae
FG
472 sdestructor.set(p);
473 ++beg;
7c673cae
FG
474 //This can throw in some containers (predicate might throw).
475 //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
476 inserter(*p);
1e59de90 477 sdestructor.release();
7c673cae
FG
478 }
479 sdestructor.release();
480 node_deallocator.release();
481 }
482 BOOST_CATCH(...){
92f5a8d4
TL
483 chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n);
484 node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain);
7c673cae
FG
485 BOOST_RETHROW
486 }
487 BOOST_CATCH_END
488 }
489 }
490
491 void clear(version_1)
492 { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
493
494 void clear(version_2)
495 {
496 typename NodeAlloc::multiallocation_chain chain;
1e59de90 497 allocator_node_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
7c673cae
FG
498 this->icont().clear_and_dispose(builder);
499 //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
500 if(!chain.empty())
501 this->node_alloc().deallocate_individual(chain);
502 }
503
504 icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_1)
505 { return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); }
506
507 icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_2)
508 {
7c673cae 509 NodeAlloc & nalloc = this->node_alloc();
1e59de90
TL
510 typename NodeAlloc::multiallocation_chain chain;
511 allocator_node_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
7c673cae
FG
512 icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
513 nalloc.deallocate_individual(chain);
514 return ret_it;
515 }
516
517 template<class Key, class Comparator>
518 size_type erase_key(const Key& k, const Comparator &comp, version_1)
519 { return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); }
520
521 template<class Key, class Comparator>
522 size_type erase_key(const Key& k, const Comparator &comp, version_2)
523 {
524 allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
525 return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder());
526 }
527
528 protected:
529 struct cloner
530 {
531 explicit cloner(node_alloc_holder &holder)
532 : m_holder(holder)
533 {}
534
535 NodePtr operator()(const Node &other) const
92f5a8d4 536 { return m_holder.create_node(other.get_real_data()); }
7c673cae
FG
537
538 node_alloc_holder &m_holder;
539 };
540
541 struct move_cloner
542 {
543 move_cloner(node_alloc_holder &holder)
544 : m_holder(holder)
545 {}
546
547 NodePtr operator()(Node &other)
92f5a8d4
TL
548 { //Use get_real_data() instead of get_real_data to allow moving const key in [multi]map
549 return m_holder.create_node(::boost::move(other.get_real_data()));
7c673cae
FG
550 }
551
552 node_alloc_holder &m_holder;
553 };
554
7c673cae 555 ICont &non_const_icont() const
92f5a8d4 556 { return const_cast<ICont&>(this->m_icont); }
7c673cae
FG
557
558 NodeAlloc &node_alloc()
92f5a8d4 559 { return static_cast<NodeAlloc &>(*this); }
7c673cae
FG
560
561 const NodeAlloc &node_alloc() const
92f5a8d4 562 { return static_cast<const NodeAlloc &>(*this); }
7c673cae
FG
563
564 public:
565 ICont &icont()
92f5a8d4 566 { return this->m_icont; }
7c673cae
FG
567
568 const ICont &icont() const
92f5a8d4
TL
569 { return this->m_icont; }
570
571 private:
572 //The intrusive container
573 ICont m_icont;
7c673cae
FG
574};
575
11fdf7f2 576} //namespace dtl {
7c673cae
FG
577} //namespace container {
578} //namespace boost {
579
580#include <boost/container/detail/config_end.hpp>
581
582#endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_