2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
5 * @file AthContainers/DataVectorWithAlloc.icc
6 * @author scott snyder <snyder@bnl.gov>
8 * @brief DataVector using a custom allocator for the elements.
12 #include "AthAllocators/exceptions.h"
18 template <class DV, class ALLOC>
20 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::UPDeleter() noexcept
26 template <class DV, class ALLOC>
28 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::UPDeleter (elt_allocator_type& heap) noexcept
34 template <class DV, class ALLOC>
36 void DataVectorWithAlloc<DV, ALLOC>::UPDeleter::operator() (value_type p)
38 using base_value_type_nc = std::remove_const_t<base_value_type>;
39 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (p));
41 m_heap->deallocate (pp, 1);
45 template <class DV, class ALLOC>
47 const typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type*
48 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::heap() const noexcept
54 template <class DV, class ALLOC>
56 DataVectorWithAlloc<DV, ALLOC>::Ptr::Ptr (std::nullptr_t) noexcept
61 template <class DV, class ALLOC>
63 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator bool() const noexcept
65 return static_cast<bool>(m_ptr);
69 template <class DV, class ALLOC>
71 typename DataVectorWithAlloc<DV, ALLOC>::Ptr&
72 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator= (std::nullptr_t) noexcept
79 template <class DV, class ALLOC>
81 void DataVectorWithAlloc<DV, ALLOC>::Ptr::swap (Ptr& other) noexcept
83 m_ptr.swap (other.m_ptr);
87 template <class DV, class ALLOC>
89 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
90 DataVectorWithAlloc<DV, ALLOC>::Ptr::get() const noexcept
96 template <class DV, class ALLOC>
98 typename std::add_lvalue_reference<typename DV::base_value_type>::type
99 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator*() const
105 template <class DV, class ALLOC>
107 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
108 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator->() const noexcept
114 template <class DV, class ALLOC>
117 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator== (const Ptr& other) const noexcept
119 return m_ptr == other.m_ptr;
123 template <class DV, class ALLOC>
126 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator< (const Ptr& other) const noexcept
128 return m_ptr < other.m_ptr;
132 template <class DV, class ALLOC>
135 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator== (std::nullptr_t) const noexcept
137 return m_ptr == nullptr;
141 template <class DV, class ALLOC>
144 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator!= (std::nullptr_t) const noexcept
146 return m_ptr != nullptr;
150 template <class DV, class ALLOC>
152 DataVectorWithAlloc<DV, ALLOC>::Ptr::Ptr (pointer p, UPDeleter&& d) noexcept
153 : m_ptr (p, std::move(d))
158 template <class DV, class ALLOC>
160 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
161 DataVectorWithAlloc<DV, ALLOC>::Ptr::release() noexcept
163 return m_ptr.release();
167 template <class DV, class ALLOC>
170 DataVectorWithAlloc<DV, ALLOC>::Ptr::checkHeap (const elt_allocator_type* other_heap) const
172 const elt_allocator_type* this_heap = m_ptr.get_deleter().heap();
173 if (this_heap && this_heap != other_heap) {
174 SG::throwExcAllocOwnership();
179 //=== Constructors, destructors, assignment.
183 * @brief Default constructor.
184 * @param eltAlloc The element allocator.
186 template <class DV, class ALLOC>
187 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
188 (elt_allocator_type&& eltAlloc /*= elt_allocator_type()*/)
190 auto del = std::make_unique<HeapDeleter> (std::move (eltAlloc));
191 m_heap = &del->heap();
192 DV::clear (std::move (del));
197 * @brief Sized constructor.
198 * @param n The size of the container.
199 * @param eltAlloc The element allocator.
201 * Note that unlike the standard vector constructor, you can't specify
202 * an initial value here. The container will be initialized with 0's.
204 template <class DV, class ALLOC>
205 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
207 elt_allocator_type&& eltAlloc /*= elt_allocator_type()*/)
209 auto del = std::make_unique<HeapDeleter> (std::move (eltAlloc));
210 m_heap = &del->heap();
211 DV::clear (std::move (del));
217 * @brief Move constructor.
218 * @param rhs The container from which to move.
220 * Any auxiliary data will be moved along with the container contents.
222 * The existing allocator is moved. @c rhs will be left with a new,
223 * default-initialized, allocator.
225 template <class DV, class ALLOC>
226 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
227 (DataVectorWithAlloc&& rhs)
228 : DV (std::move (rhs)),
231 auto del = std::make_unique<HeapDeleter> (elt_allocator_type());
232 rhs.m_heap = &del->heap();
233 static_cast<DV&>(rhs).clear (std::move (del));
238 * @brief Move assignment.
239 * @param rhs The container from which to move.
241 * Any auxiliary data will be moved along with the container contents.
243 * The existing allocator is moved. @c rhs will be left with a new,
244 * default-initialized, allocator.
246 template <class DV, class ALLOC>
247 DataVectorWithAlloc<DV, ALLOC>&
248 DataVectorWithAlloc<DV, ALLOC>::operator= (DataVectorWithAlloc&& rhs)
251 DV::operator= (std::move (rhs));
253 auto del = std::make_unique<HeapDeleter> (elt_allocator_type());
254 rhs.m_heap = &del->heap();
255 static_cast<DV&>(rhs).clear (std::move (del));
264 template <class DV, class ALLOC>
265 DataVectorWithAlloc<DV, ALLOC>::~DataVectorWithAlloc()
267 // If the heap memory was protected, unprotect it now.
269 SG::maybeUnprotect (*m_heap);
271 catch (const SG::ExcProtection&) {
272 // Got an error from mprotect...
279 * @brief Return the underlying allocator.
281 template <class DV, class ALLOC>
283 const typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
284 DataVectorWithAlloc<DV, ALLOC>::elt_allocator() const
291 * @brief Return the underlying allocator.
293 template <class DV, class ALLOC>
295 typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
296 DataVectorWithAlloc<DV, ALLOC>::elt_allocator()
302 //=== Size and capacity.
306 * @fn void reserve (size_type n)
307 * @brief Attempt to preallocate enough memory for a specified number
309 * @param n Number of elements required.
311 template <class DV, class ALLOC>
312 void DataVectorWithAlloc<DV, ALLOC>::reserve (size_type n)
320 * @brief Change the vector capacity to match the current size.
322 * Note: this does not affect auxiliary data.
324 template <class DV, class ALLOC>
325 void DataVectorWithAlloc<DV, ALLOC>::shrink_to_fit()
328 m_heap->reserve (size());
332 //=== Element access.
336 * @brief Access an element, as an lvalue.
337 * @param n Array index to access.
338 * @return Proxy to the element at @a n.
340 * No bounds checking is done.
341 * Note that we return a proxy object rather than a reference;
342 * the proxy will handle deleting an owned element if it's assigned to.
344 template <class DV, class ALLOC>
346 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
347 DataVectorWithAlloc<DV, ALLOC>::operator[] (size_type n)
349 return to_element_proxy (this->m_pCont.begin() + n);
354 * @brief Access an element, as an lvalue.
355 * @param n Array index to access.
356 * @return Proxy to the element at @a n.
358 * Will raise @c std::out_of_range if the index is out-of-bounds.
359 * Note that we return a proxy object rather than a reference;
360 * the proxy will handle deleting an owned element if it's assigned to.
362 template <class DV, class ALLOC>
364 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
365 DataVectorWithAlloc<DV, ALLOC>::at (size_type n)
367 if (n >= this->size())
368 throw std::out_of_range ("DataVector::at range check");
369 return to_element_proxy (this->m_pCont.begin() + n);
374 * @brief Access the first element in the collection as an lvalue.
375 * @return Proxy to the first element in the collection.
377 * No checking is done to ensure that the container is not empty.
378 * Note that we return a proxy object rather than a reference;
379 * the proxy will handle deleting an owned element if it's assigned to.
381 template <class DV, class ALLOC>
383 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
384 DataVectorWithAlloc<DV, ALLOC>::front ()
386 return to_element_proxy (this->m_pCont.begin());
391 * @brief Access the last element in the collection as an lvalue.
392 * @return Proxy to the last element in the collection.
394 * No checking is done to ensure that the container is not empty.
395 * Note that we return a proxy object rather than a reference;
396 * the proxy will handle deleting an owned element if it's assigned to.
398 template <class DV, class ALLOC>
400 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
401 DataVectorWithAlloc<DV, ALLOC>::back ()
403 return to_element_proxy (this->m_pCont.end()-1);
407 //=== Iterator creation.
411 * @brief Return an @c iterator pointing at the beginning
413 * @return An @c iterator.
415 * Note that dereferencing the iterator will yield a proxy rather
416 * than a reference; the proxy will handle deleting an owned element
417 * if it's assigned to.
419 template <class DV, class ALLOC>
421 typename DataVectorWithAlloc<DV, ALLOC>::iterator
422 DataVectorWithAlloc<DV, ALLOC>::begin() noexcept
424 return to_my_iterator (DV::begin());
429 * @brief Return an @c iterator pointing past the end
431 * @return An @c iterator.
433 * Note that dereferencing the iterator will yield a proxy rather
434 * than a reference; the proxy will handle deleting an owned element
435 * if it's assigned to.
437 template <class DV, class ALLOC>
439 typename DataVectorWithAlloc<DV, ALLOC>::iterator
440 DataVectorWithAlloc<DV, ALLOC>::end() noexcept
442 return to_my_iterator (DV::end());
447 * @brief Return a @c reverse_iterator pointing past the end
449 * @return A @c reverse_iterator.
451 * Note that dereferencing the iterator will yield a proxy rather
452 * than a reference; the proxy will handle deleting an owned element
453 * if it's assigned to.
455 template <class DV, class ALLOC>
457 typename DataVectorWithAlloc<DV, ALLOC>::reverse_iterator
458 DataVectorWithAlloc<DV, ALLOC>::rbegin() noexcept
460 return reverse_iterator (to_my_iterator (DV::end()));
465 * @brief Return a @c reverse_iterator pointing at the beginning
467 * @return A @c reverse_iterator.
469 * Note that dereferencing the iterator will yield a proxy rather
470 * than a reference; the proxy will handle deleting an owned element
471 * if it's assigned to.
473 template <class DV, class ALLOC>
475 typename DataVectorWithAlloc<DV, ALLOC>::reverse_iterator
476 DataVectorWithAlloc<DV, ALLOC>::rend() noexcept
478 return reverse_iterator (to_my_iterator (DV::begin()));
482 //=== Insertion operations.
486 * @brief Add an element to the end of the collection.
487 * @param pElem The element to add to the collection.
489 * Note: this method may only be called using the most derived
490 * @c DataVector in the hierarchy.
492 * Returns the pushed pointer.
494 template <class DV, class ALLOC>
496 typename DataVectorWithAlloc<DV, ALLOC>::value_type
497 DataVectorWithAlloc<DV, ALLOC>::push_back (Ptr pElem)
499 pElem.checkHeap (m_heap);
500 typename DV::value_type p = pElem.release();
507 * @brief Create and add a number of new elements to the end of the container.
508 * @param n The number of new elements to add.
509 * The elements will be created by calling allocate().
511 * Note: this method may only be called using the most derived
512 * @c DataVector in the hierarchy.
514 * Returns the original size of the vector.
516 template <class DV, class ALLOC>
519 DataVectorWithAlloc<DV, ALLOC>::push_new (size_type n) ->size_type
522 typename elt_allocator_type::pointer p = m_heap->allocate(1);
523 // Note: not protected against exceptions.
524 m_heap->construct (p);
527 return DV::push_new (n, alloc);
532 * @brief Add an element to the end of the collection.
533 * @param pElem The element to add to the collection.
535 * Note: this method may only be called using the most derived
536 * @c DataVector in the hierarchy.
538 * For @c DataVector, this is like the same as @c push_back, and
539 * it returns the pushed element.
540 * It's included just for interface compatibility with `std::vector`.
542 template <class DV, class ALLOC>
544 typename DataVectorWithAlloc<DV, ALLOC>::value_type
545 DataVectorWithAlloc<DV, ALLOC>::emplace_back (Ptr pElem)
547 return push_back (std::move (pElem));
552 * @brief Add a new element to the collection.
553 * @param position Iterator before which the element will be added.
554 * @param pElem The element to add to the collection.
555 * @return An iterator that points to the inserted data.
557 * The container's ownership policy will determine if it takes ownership
558 * of the new element.
560 * Note: this method may only be called using the most derived
561 * @c DataVector in the hierarchy.
563 template <class DV, class ALLOC>
565 typename DataVectorWithAlloc<DV, ALLOC>::iterator
566 DataVectorWithAlloc<DV, ALLOC>::insert(iterator position, Ptr pElem)
568 pElem.checkHeap (m_heap);
569 return to_my_iterator
570 (DV::insert (to_base_iterator (position), pElem.release()));
575 * @brief Add a new element to the collection.
576 * @param position Iterator before which the element will be added.
577 * @param pElem The element to add to the collection.
578 * @return An iterator that points to the inserted data.
580 * Note: this method may only be called using the most derived
581 * @c DataVector in the hierarchy.
583 * For @c DataVector, this is just the same as @c insert.
584 * It's included just for interface compatibility with `std::vector`.
586 template <class DV, class ALLOC>
588 typename DataVectorWithAlloc<DV, ALLOC>::iterator
589 DataVectorWithAlloc<DV, ALLOC>::emplace(iterator position, Ptr pElem)
591 return this->insert (position, std::move(pElem));
595 //=== Erasure operations.
599 * @brief Remove element at a given position.
600 * @param position Iterator pointing to the element to be removed.
601 * @return An iterator pointing to the next element (or @c end()).
603 * The pointed-to element will be deleted.
605 template <class DV, class ALLOC>
607 typename DataVectorWithAlloc<DV, ALLOC>::iterator
608 DataVectorWithAlloc<DV, ALLOC>::erase(iterator position)
610 return to_my_iterator (DV::erase (to_base_iterator (position)));
615 * @brief Remove a range of elements.
616 * @param first Iterator pointing to the first element to be removed.
617 * @param last Iterator pointing one past the last element to be removed.
618 * @return An iterator pointing to the element pointed to by @a last
619 * prior to erasing (or @c end()).
621 * The removed elements will be deleted.
623 template <class DV, class ALLOC>
625 typename DataVectorWithAlloc<DV, ALLOC>::iterator
626 DataVectorWithAlloc<DV, ALLOC>::erase(iterator first, iterator last)
628 return to_my_iterator
629 (DV::erase (to_base_iterator (first),
630 to_base_iterator (last)));
636 * @brief Erase all the elements in the collection.
638 * The removed elements will be deleted.
640 template <class DV, class ALLOC>
642 void DataVectorWithAlloc<DV, ALLOC>::clear()
652 * @brief Swap this collection with another.
653 * @param rhs The collection with which to swap.
655 * Ownership is swapped along with the collection content.
657 * Note: this method may only be called using the most-derived
658 * @c DataVector in the hierarchy. The @a rhs must also be
659 * referenced using the most-derived @c DataVector.
661 template <class DV, class ALLOC>
663 void DataVectorWithAlloc<DV, ALLOC>::swap (DataVectorWithAlloc& rhs)
666 std::swap (m_heap, rhs.m_heap);
671 * @brief Swap the referents of two @c DataVector iterators.
672 * @param a The first iterator for the swap.
673 * @param b The second iterator for the swap.
675 * The iterators must both refer to the same container.
677 template <class DV, class ALLOC>
679 void DataVectorWithAlloc<DV, ALLOC>::iter_swap (iterator a, iterator b)
681 if (a.container() != b.container()) {
682 throw SG::ExcBadIterSwap();
684 DV::iter_swap (to_base_iterator (a),
685 to_base_iterator (b));
689 //=== Non-standard operations.
693 * @brief Swap one element out of the container.
694 * @param index Index of the element in the container to swap.
695 * @param newElem New element to put in the container.
697 * @param oldElem Reference to receive the element removed from the
700 * Reference @a oldElem is initialized with element @a index of the
701 * collection (no bounds checking). Then element @a index is set
704 * Note: this method may only be called using the most derived
705 * @c DataVector in the hierarchy.
707 template <class DV, class ALLOC>
710 DataVectorWithAlloc<DV, ALLOC>::swapElement (size_type index,
714 newElem.checkHeap (m_heap);
715 typename DV::value_type pnew = newElem.release();
716 typename DV::value_type pold = nullptr;
717 DV::swapElement (index, pnew, pold);
718 oldElem = Ptr (pold, UPDeleter (*m_heap));
723 * @brief Swap one element out of the container.
724 * @param pos The element in the container to swap.
725 * @param newElem New element to put in the container.
727 * @param oldElem Reference to receive the element removed from the
730 * Reference @a oldElem is initialized with element @a pos of the
731 * collection (no bounds checking). Then element @a index is set
734 * Note: this method may only be called using the most derived
735 * @c DataList in the hierarchy.
737 template <class DV, class ALLOC>
740 DataVectorWithAlloc<DV, ALLOC>::swapElement (iterator pos,
744 newElem.checkHeap (m_heap);
745 typename DV::value_type pnew = newElem.release();
746 typename DV::value_type pold = nullptr;
747 DV::swapElement (to_base_iterator(pos), pnew, pold);
748 oldElem = Ptr (pold, UPDeleter (*m_heap));
753 * @brief Return a pointer to this object, as a const @c DataVector.
755 template <class DV, class ALLOC>
758 DataVectorWithAlloc<DV, ALLOC>::asDataVector() const
760 return static_cast<const DV*>(this);
765 * @brief Cast from a @c DataVector to a @c DataVectorWithAlloc.
766 * @param dv Pointer to object to cast.
768 * Return @c DV cast to a @c DataVectorWithAlloc.
770 template <class DV, class ALLOC>
771 const DataVectorWithAlloc<DV, ALLOC>*
772 DataVectorWithAlloc<DV, ALLOC>::fromDataVector (const DV* dv)
774 if (typeid (*dv) == typeid (DataVectorWithAlloc))
775 return static_cast<const DataVectorWithAlloc*> (dv);
781 * @brief Reset indices / reorder aux data after elements have been permuted.
782 * @param beg Start of the range of elements to process.
783 * @param end End of the range of elements to process.
785 template <class DV, class ALLOC>
787 void DataVectorWithAlloc<DV, ALLOC>::resortAux (iterator beg, iterator end)
789 DV::resortAux (to_base_iterator(beg), to_base_iterator(end));
794 * @brief Convert to @c AuxVectorBase.
796 * Needed to get @x AuxVectorBase from a @c DataVectorWithAlloc.
797 * Present in @c DataVector as well for consistency.
799 template <class DV, class ALLOC>
801 const SG::AuxVectorBase& DataVectorWithAlloc<DV, ALLOC>::auxbase() const
808 * @brief Allocate a new vector element.
810 * Arguments will be forwarded to the element constructor.
812 template <class DV, class ALLOC>
813 template <class... Args>
814 typename DataVectorWithAlloc<DV, ALLOC>::Ptr
815 DataVectorWithAlloc<DV, ALLOC>::allocate (Args&&... args)
817 typename elt_allocator_type::pointer p = m_heap->allocate(1);
819 m_heap->construct (p, std::forward<Args>(args)...);
822 m_heap->deallocate (p, 1);
825 return Ptr (p, UPDeleter (*m_heap));
829 //=== Relational operators.
833 * @brief Vector ordering relation.
834 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
835 * @return True iff @a *this is lexicographically less than @a b.
837 * This is a total ordering relation. It is linear in the size of the
838 * vectors. Comparisons are done on the pointer values of the elements.
840 * See @c std::lexicographical_compare() for how the determination is made.
842 template <class DV, class ALLOC>
844 bool DataVectorWithAlloc<DV, ALLOC>::operator< (const DataVectorWithAlloc& b) const
846 return static_cast<const DV&>(*this) < static_cast<const DV&>(b);
850 /// Based on operator<
851 template <class DV, class ALLOC>
853 bool DataVectorWithAlloc<DV, ALLOC>::operator> (const DataVectorWithAlloc& b) const
855 return static_cast<const DV&>(*this) > static_cast<const DV&>(b);
859 /// Based on operator<
860 template <class DV, class ALLOC>
862 bool DataVectorWithAlloc<DV, ALLOC>::operator<= (const DataVectorWithAlloc& b) const
864 return static_cast<const DV&>(*this) <= static_cast<const DV&>(b);
868 /// Based on operator<
869 template <class DV, class ALLOC>
871 bool DataVectorWithAlloc<DV, ALLOC>::operator>= (const DataVectorWithAlloc& b) const
873 return static_cast<const DV&>(*this) >= static_cast<const DV&>(b);
878 * @brief Vector equality comparison.
879 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
880 * @return True iff the size and elements of the vectors are equal.
882 * This is an equivalence relation. It is linear in the size of the
883 * vectors. Vectors are considered equivalent if their sizes are equal,
884 * and if corresponding elements compare equal.
886 template <class DV, class ALLOC>
888 bool DataVectorWithAlloc<DV, ALLOC>::operator== (const DataVectorWithAlloc& b) const
890 return static_cast<const DV&>(*this) == static_cast<const DV&>(b);
894 /// Based on operator==
895 template <class DV, class ALLOC>
897 bool DataVectorWithAlloc<DV, ALLOC>::operator!= (const DataVectorWithAlloc& b) const
899 return static_cast<const DV&>(*this) != static_cast<const DV&>(b);
903 //=== Private helpers.
907 * @brief Handle element assignment.
908 * @param pos Position in the container to assign.
909 * @param newElem The new element to assign.
911 * Auxiliary data are copied if appropriate.
913 template <class DV, class ALLOC>
916 DataVectorWithAlloc<DV, ALLOC>::assignElement (typename BaseContainer::iterator pos,
919 newElem.checkHeap (m_heap);
920 DV::assignElement (pos, newElem.release());
925 * @brief Convert a @c DataVectorWithAlloc::iterator to an iterator
926 * of the base @c DataVector.
927 * @param it The @c DataVectorWithAlloc::iterator to convert.
929 template <class DV, class ALLOC>
931 typename DV::iterator
932 DataVectorWithAlloc<DV, ALLOC>::to_base_iterator (iterator it)
934 return typename DV::iterator (it.base(), it.container());
939 * @brief Convert an iterator of the base @c DataVector to
940 * a @c DataVectorWithAlloc::iterator.
941 * @param it The base @c DataVector iterator to convert.
943 template <class DV, class ALLOC>
945 typename DataVectorWithAlloc<DV, ALLOC>::iterator
946 DataVectorWithAlloc<DV, ALLOC>::to_my_iterator (typename DV::iterator it)
948 return iterator (it.base(), this);
953 * @brief Convert an iterator of the base @c vector to
954 * an @c ElementProxy for the @c DataVectorWithAlloc.
955 * @param it The base @c vector iterator to convert.
957 template <class DV, class ALLOC>
959 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
960 DataVectorWithAlloc<DV, ALLOC>::to_element_proxy (typename BaseContainer::iterator i)
962 return ElementProxy (i, this);
966 template <class DV, class ALLOC>
967 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::HeapDeleter (elt_allocator_type&& heap)
968 : m_heap (std::move (heap))
973 template <class DV, class ALLOC>
974 typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
975 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::heap() noexcept
981 template <class DV, class ALLOC>
982 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete (value_type p)
985 using base_value_type_nc = std::remove_const_t<base_value_type>;
986 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (p));
988 m_heap.deallocate (pp, 1);
993 template <class DV, class ALLOC>
994 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete
995 (typename PtrVector::iterator first,
996 typename PtrVector::iterator last)
998 for (; first != last; ++first) {
1000 using base_value_type_nc = std::remove_const_t<base_value_type>;
1001 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (*first));
1002 m_heap.destroy (pp);
1003 m_heap.deallocate (pp, 1);