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"
13 #include "CxxUtils/throw_out_of_range.h"
19 template <class DV, class ALLOC>
21 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::UPDeleter() noexcept
27 template <class DV, class ALLOC>
29 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::UPDeleter (elt_allocator_type& heap) noexcept
35 template <class DV, class ALLOC>
37 void DataVectorWithAlloc<DV, ALLOC>::UPDeleter::operator() (value_type p)
39 using base_value_type_nc = std::remove_const_t<base_value_type>;
40 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (p));
42 m_heap->deallocate (pp, 1);
46 template <class DV, class ALLOC>
48 const typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type*
49 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::heap() const noexcept
55 template <class DV, class ALLOC>
57 DataVectorWithAlloc<DV, ALLOC>::Ptr::Ptr (std::nullptr_t) noexcept
62 template <class DV, class ALLOC>
64 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator bool() const noexcept
66 return static_cast<bool>(m_ptr);
70 template <class DV, class ALLOC>
72 typename DataVectorWithAlloc<DV, ALLOC>::Ptr&
73 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator= (std::nullptr_t) noexcept
80 template <class DV, class ALLOC>
82 void DataVectorWithAlloc<DV, ALLOC>::Ptr::swap (Ptr& other) noexcept
84 m_ptr.swap (other.m_ptr);
88 template <class DV, class ALLOC>
90 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
91 DataVectorWithAlloc<DV, ALLOC>::Ptr::get() const noexcept
97 template <class DV, class ALLOC>
99 typename std::add_lvalue_reference<typename DV::base_value_type>::type
100 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator*() const
106 template <class DV, class ALLOC>
108 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
109 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator->() const noexcept
115 template <class DV, class ALLOC>
118 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator== (const Ptr& other) const noexcept
120 return m_ptr == other.m_ptr;
124 template <class DV, class ALLOC>
127 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator< (const Ptr& other) const noexcept
129 return m_ptr < other.m_ptr;
133 template <class DV, class ALLOC>
136 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator== (std::nullptr_t) const noexcept
138 return m_ptr == nullptr;
142 template <class DV, class ALLOC>
145 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator!= (std::nullptr_t) const noexcept
147 return m_ptr != nullptr;
151 template <class DV, class ALLOC>
153 DataVectorWithAlloc<DV, ALLOC>::Ptr::Ptr (pointer p, UPDeleter&& d) noexcept
154 : m_ptr (p, std::move(d))
159 template <class DV, class ALLOC>
161 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
162 DataVectorWithAlloc<DV, ALLOC>::Ptr::release() noexcept
164 return m_ptr.release();
168 template <class DV, class ALLOC>
171 DataVectorWithAlloc<DV, ALLOC>::Ptr::checkHeap (const elt_allocator_type* other_heap) const
173 const elt_allocator_type* this_heap = m_ptr.get_deleter().heap();
174 if (this_heap && this_heap != other_heap) {
175 SG::throwExcAllocOwnership();
180 //=== Constructors, destructors, assignment.
184 * @brief Default constructor.
185 * @param eltAlloc The element allocator.
187 template <class DV, class ALLOC>
188 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
189 (elt_allocator_type&& eltAlloc /*= elt_allocator_type()*/)
191 auto del = std::make_unique<HeapDeleter> (std::move (eltAlloc));
192 m_heap = &del->heap();
193 DV::clear (std::move (del));
198 * @brief Sized constructor.
199 * @param n The size of the container.
200 * @param eltAlloc The element allocator.
202 * Note that unlike the standard vector constructor, you can't specify
203 * an initial value here. The container will be initialized with 0's.
205 template <class DV, class ALLOC>
206 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
208 elt_allocator_type&& eltAlloc /*= elt_allocator_type()*/)
210 auto del = std::make_unique<HeapDeleter> (std::move (eltAlloc));
211 m_heap = &del->heap();
212 DV::clear (std::move (del));
218 * @brief Move constructor.
219 * @param rhs The container from which to move.
221 * Any auxiliary data will be moved along with the container contents.
223 * The existing allocator is moved. @c rhs will be left with a new,
224 * default-initialized, allocator.
226 template <class DV, class ALLOC>
227 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
228 (DataVectorWithAlloc&& rhs)
229 : DV (std::move (rhs)),
232 auto del = std::make_unique<HeapDeleter> (elt_allocator_type());
233 rhs.m_heap = &del->heap();
234 static_cast<DV&>(rhs).clear (std::move (del));
239 * @brief Move assignment.
240 * @param rhs The container from which to move.
242 * Any auxiliary data will be moved along with the container contents.
244 * The existing allocator is moved. @c rhs will be left with a new,
245 * default-initialized, allocator.
247 template <class DV, class ALLOC>
248 DataVectorWithAlloc<DV, ALLOC>&
249 DataVectorWithAlloc<DV, ALLOC>::operator= (DataVectorWithAlloc&& rhs)
252 DV::operator= (std::move (rhs));
254 auto del = std::make_unique<HeapDeleter> (elt_allocator_type());
255 rhs.m_heap = &del->heap();
256 static_cast<DV&>(rhs).clear (std::move (del));
265 template <class DV, class ALLOC>
266 DataVectorWithAlloc<DV, ALLOC>::~DataVectorWithAlloc()
268 // If the heap memory was protected, unprotect it now.
270 SG::maybeUnprotect (*m_heap);
272 catch (const SG::ExcProtection&) {
273 // Got an error from mprotect...
280 * @brief Return the underlying allocator.
282 template <class DV, class ALLOC>
284 const typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
285 DataVectorWithAlloc<DV, ALLOC>::elt_allocator() const
292 * @brief Return the underlying allocator.
294 template <class DV, class ALLOC>
296 typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
297 DataVectorWithAlloc<DV, ALLOC>::elt_allocator()
303 //=== Size and capacity.
307 * @fn void reserve (size_type n)
308 * @brief Attempt to preallocate enough memory for a specified number
310 * @param n Number of elements required.
312 template <class DV, class ALLOC>
313 void DataVectorWithAlloc<DV, ALLOC>::reserve (size_type n)
321 * @brief Change the vector capacity to match the current size.
323 * Note: this does not affect auxiliary data.
325 template <class DV, class ALLOC>
326 void DataVectorWithAlloc<DV, ALLOC>::shrink_to_fit()
329 m_heap->reserve (size());
333 //=== Element access.
337 * @brief Access an element, as an lvalue.
338 * @param n Array index to access.
339 * @return Proxy to the element at @a n.
341 * No bounds checking is done.
342 * Note that we return a proxy object rather than a reference;
343 * the proxy will handle deleting an owned element if it's assigned to.
345 template <class DV, class ALLOC>
347 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
348 DataVectorWithAlloc<DV, ALLOC>::operator[] (size_type n)
350 return to_element_proxy (this->m_pCont.begin() + n);
355 * @brief Access an element, as an lvalue.
356 * @param n Array index to access.
357 * @return Proxy to the element at @a n.
359 * Will raise @c std::out_of_range if the index is out-of-bounds.
360 * Note that we return a proxy object rather than a reference;
361 * the proxy will handle deleting an owned element if it's assigned to.
363 template <class DV, class ALLOC>
365 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
366 DataVectorWithAlloc<DV, ALLOC>::at (size_type n)
368 if (n >= this->size())
369 CxxUtils::throw_out_of_range (__PRETTY_FUNCTION__, n, this->size(), this);
370 return to_element_proxy (this->m_pCont.begin() + n);
375 * @brief Access the first element in the collection as an lvalue.
376 * @return Proxy to the first element in the collection.
378 * No checking is done to ensure that the container is not empty.
379 * Note that we return a proxy object rather than a reference;
380 * the proxy will handle deleting an owned element if it's assigned to.
382 template <class DV, class ALLOC>
384 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
385 DataVectorWithAlloc<DV, ALLOC>::front ()
387 return to_element_proxy (this->m_pCont.begin());
392 * @brief Access the last element in the collection as an lvalue.
393 * @return Proxy to the last element in the collection.
395 * No checking is done to ensure that the container is not empty.
396 * Note that we return a proxy object rather than a reference;
397 * the proxy will handle deleting an owned element if it's assigned to.
399 template <class DV, class ALLOC>
401 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
402 DataVectorWithAlloc<DV, ALLOC>::back ()
404 return to_element_proxy (this->m_pCont.end()-1);
408 //=== Iterator creation.
412 * @brief Return an @c iterator pointing at the beginning
414 * @return An @c iterator.
416 * Note that dereferencing the iterator will yield a proxy rather
417 * than a reference; the proxy will handle deleting an owned element
418 * if it's assigned to.
420 template <class DV, class ALLOC>
422 typename DataVectorWithAlloc<DV, ALLOC>::iterator
423 DataVectorWithAlloc<DV, ALLOC>::begin() noexcept
425 return to_my_iterator (DV::begin());
430 * @brief Return an @c iterator pointing past the end
432 * @return An @c iterator.
434 * Note that dereferencing the iterator will yield a proxy rather
435 * than a reference; the proxy will handle deleting an owned element
436 * if it's assigned to.
438 template <class DV, class ALLOC>
440 typename DataVectorWithAlloc<DV, ALLOC>::iterator
441 DataVectorWithAlloc<DV, ALLOC>::end() noexcept
443 return to_my_iterator (DV::end());
448 * @brief Return a @c reverse_iterator pointing past the end
450 * @return A @c reverse_iterator.
452 * Note that dereferencing the iterator will yield a proxy rather
453 * than a reference; the proxy will handle deleting an owned element
454 * if it's assigned to.
456 template <class DV, class ALLOC>
458 typename DataVectorWithAlloc<DV, ALLOC>::reverse_iterator
459 DataVectorWithAlloc<DV, ALLOC>::rbegin() noexcept
461 return reverse_iterator (to_my_iterator (DV::end()));
466 * @brief Return a @c reverse_iterator pointing at the beginning
468 * @return A @c reverse_iterator.
470 * Note that dereferencing the iterator will yield a proxy rather
471 * than a reference; the proxy will handle deleting an owned element
472 * if it's assigned to.
474 template <class DV, class ALLOC>
476 typename DataVectorWithAlloc<DV, ALLOC>::reverse_iterator
477 DataVectorWithAlloc<DV, ALLOC>::rend() noexcept
479 return reverse_iterator (to_my_iterator (DV::begin()));
483 //=== Insertion operations.
487 * @brief Add an element to the end of the collection.
488 * @param pElem The element to add to the collection.
490 * Note: this method may only be called using the most derived
491 * @c DataVector in the hierarchy.
493 * Returns the pushed pointer.
495 template <class DV, class ALLOC>
497 typename DataVectorWithAlloc<DV, ALLOC>::value_type
498 DataVectorWithAlloc<DV, ALLOC>::push_back (Ptr pElem)
500 pElem.checkHeap (m_heap);
501 typename DV::value_type p = pElem.release();
508 * @brief Create and add a number of new elements to the end of the container.
509 * @param n The number of new elements to add.
510 * The elements will be created by calling allocate().
512 * Note: this method may only be called using the most derived
513 * @c DataVector in the hierarchy.
515 * Returns the original size of the vector.
517 template <class DV, class ALLOC>
520 DataVectorWithAlloc<DV, ALLOC>::push_new (size_type n) ->size_type
523 typename elt_allocator_type::pointer p = m_heap->allocate(1);
524 // Note: not protected against exceptions.
525 m_heap->construct (p);
528 return DV::push_new (n, alloc);
533 * @brief Add an element to the end of the collection.
534 * @param pElem The element to add to the collection.
536 * Note: this method may only be called using the most derived
537 * @c DataVector in the hierarchy.
539 * For @c DataVector, this is like the same as @c push_back, and
540 * it returns the pushed element.
541 * It's included just for interface compatibility with `std::vector`.
543 template <class DV, class ALLOC>
545 typename DataVectorWithAlloc<DV, ALLOC>::value_type
546 DataVectorWithAlloc<DV, ALLOC>::emplace_back (Ptr pElem)
548 return push_back (std::move (pElem));
553 * @brief Add a new element to the collection.
554 * @param position Iterator before which the element will be added.
555 * @param pElem The element to add to the collection.
556 * @return An iterator that points to the inserted data.
558 * The container's ownership policy will determine if it takes ownership
559 * of the new element.
561 * Note: this method may only be called using the most derived
562 * @c DataVector in the hierarchy.
564 template <class DV, class ALLOC>
566 typename DataVectorWithAlloc<DV, ALLOC>::iterator
567 DataVectorWithAlloc<DV, ALLOC>::insert(iterator position, Ptr pElem)
569 pElem.checkHeap (m_heap);
570 return to_my_iterator
571 (DV::insert (to_base_iterator (position), pElem.release()));
576 * @brief Add a new element to the collection.
577 * @param position Iterator before which the element will be added.
578 * @param pElem The element to add to the collection.
579 * @return An iterator that points to the inserted data.
581 * Note: this method may only be called using the most derived
582 * @c DataVector in the hierarchy.
584 * For @c DataVector, this is just the same as @c insert.
585 * It's included just for interface compatibility with `std::vector`.
587 template <class DV, class ALLOC>
589 typename DataVectorWithAlloc<DV, ALLOC>::iterator
590 DataVectorWithAlloc<DV, ALLOC>::emplace(iterator position, Ptr pElem)
592 return this->insert (position, std::move(pElem));
596 //=== Erasure operations.
600 * @brief Remove element at a given position.
601 * @param position Iterator pointing to the element to be removed.
602 * @return An iterator pointing to the next element (or @c end()).
604 * The pointed-to element will be deleted.
606 template <class DV, class ALLOC>
608 typename DataVectorWithAlloc<DV, ALLOC>::iterator
609 DataVectorWithAlloc<DV, ALLOC>::erase(iterator position)
611 return to_my_iterator (DV::erase (to_base_iterator (position)));
616 * @brief Remove a range of elements.
617 * @param first Iterator pointing to the first element to be removed.
618 * @param last Iterator pointing one past the last element to be removed.
619 * @return An iterator pointing to the element pointed to by @a last
620 * prior to erasing (or @c end()).
622 * The removed elements will be deleted.
624 template <class DV, class ALLOC>
626 typename DataVectorWithAlloc<DV, ALLOC>::iterator
627 DataVectorWithAlloc<DV, ALLOC>::erase(iterator first, iterator last)
629 return to_my_iterator
630 (DV::erase (to_base_iterator (first),
631 to_base_iterator (last)));
637 * @brief Erase all the elements in the collection.
639 * The removed elements will be deleted.
641 template <class DV, class ALLOC>
643 void DataVectorWithAlloc<DV, ALLOC>::clear()
653 * @brief Swap this collection with another.
654 * @param rhs The collection with which to swap.
656 * Ownership is swapped along with the collection content.
658 * Note: this method may only be called using the most-derived
659 * @c DataVector in the hierarchy. The @a rhs must also be
660 * referenced using the most-derived @c DataVector.
662 template <class DV, class ALLOC>
664 void DataVectorWithAlloc<DV, ALLOC>::swap (DataVectorWithAlloc& rhs)
667 std::swap (m_heap, rhs.m_heap);
672 * @brief Swap the referents of two @c DataVector iterators.
673 * @param a The first iterator for the swap.
674 * @param b The second iterator for the swap.
676 * The iterators must both refer to the same container.
678 template <class DV, class ALLOC>
680 void DataVectorWithAlloc<DV, ALLOC>::iter_swap (iterator a, iterator b)
682 if (a.container() != b.container()) {
683 throw SG::ExcBadIterSwap();
685 DV::iter_swap (to_base_iterator (a),
686 to_base_iterator (b));
690 //=== Non-standard operations.
694 * @brief Swap one element out of the container.
695 * @param index Index of the element in the container to swap.
696 * @param newElem New element to put in the container.
698 * @param oldElem Reference to receive the element removed from the
701 * Reference @a oldElem is initialized with element @a index of the
702 * collection (no bounds checking). Then element @a index is set
705 * Note: this method may only be called using the most derived
706 * @c DataVector in the hierarchy.
708 template <class DV, class ALLOC>
711 DataVectorWithAlloc<DV, ALLOC>::swapElement (size_type index,
715 newElem.checkHeap (m_heap);
716 typename DV::value_type pnew = newElem.release();
717 typename DV::value_type pold = nullptr;
718 DV::swapElement (index, pnew, pold);
719 oldElem = Ptr (pold, UPDeleter (*m_heap));
724 * @brief Swap one element out of the container.
725 * @param pos The element in the container to swap.
726 * @param newElem New element to put in the container.
728 * @param oldElem Reference to receive the element removed from the
731 * Reference @a oldElem is initialized with element @a pos of the
732 * collection (no bounds checking). Then element @a index is set
735 * Note: this method may only be called using the most derived
736 * @c DataList in the hierarchy.
738 template <class DV, class ALLOC>
741 DataVectorWithAlloc<DV, ALLOC>::swapElement (iterator pos,
745 newElem.checkHeap (m_heap);
746 typename DV::value_type pnew = newElem.release();
747 typename DV::value_type pold = nullptr;
748 DV::swapElement (to_base_iterator(pos), pnew, pold);
749 oldElem = Ptr (pold, UPDeleter (*m_heap));
754 * @brief Return a pointer to this object, as a const @c DataVector.
756 template <class DV, class ALLOC>
759 DataVectorWithAlloc<DV, ALLOC>::asDataVector() const
761 return static_cast<const DV*>(this);
766 * @brief Cast from a @c DataVector to a @c DataVectorWithAlloc.
767 * @param dv Pointer to object to cast.
769 * Return @c DV cast to a @c DataVectorWithAlloc.
771 template <class DV, class ALLOC>
772 const DataVectorWithAlloc<DV, ALLOC>*
773 DataVectorWithAlloc<DV, ALLOC>::fromDataVector (const DV* dv)
775 if (typeid (*dv) == typeid (DataVectorWithAlloc))
776 return static_cast<const DataVectorWithAlloc*> (dv);
782 * @brief Reset indices / reorder aux data after elements have been permuted.
783 * @param beg Start of the range of elements to process.
784 * @param end End of the range of elements to process.
786 template <class DV, class ALLOC>
788 void DataVectorWithAlloc<DV, ALLOC>::resortAux (iterator beg, iterator end)
790 DV::resortAux (to_base_iterator(beg), to_base_iterator(end));
795 * @brief Convert to @c AuxVectorBase.
797 * Needed to get @x AuxVectorBase from a @c DataVectorWithAlloc.
798 * Present in @c DataVector as well for consistency.
800 template <class DV, class ALLOC>
802 const SG::AuxVectorBase& DataVectorWithAlloc<DV, ALLOC>::auxbase() const
809 * @brief Allocate a new vector element.
811 * Arguments will be forwarded to the element constructor.
813 template <class DV, class ALLOC>
814 template <class... Args>
815 typename DataVectorWithAlloc<DV, ALLOC>::Ptr
816 DataVectorWithAlloc<DV, ALLOC>::allocate (Args&&... args)
818 typename elt_allocator_type::pointer p = m_heap->allocate(1);
820 m_heap->construct (p, std::forward<Args>(args)...);
823 m_heap->deallocate (p, 1);
826 return Ptr (p, UPDeleter (*m_heap));
830 //=== Relational operators.
834 * @brief Vector ordering relation.
835 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
836 * @return True iff @a *this is lexicographically less than @a b.
838 * This is a total ordering relation. It is linear in the size of the
839 * vectors. Comparisons are done on the pointer values of the elements.
841 * See @c std::lexicographical_compare() for how the determination is made.
843 template <class DV, class ALLOC>
845 bool DataVectorWithAlloc<DV, ALLOC>::operator< (const DataVectorWithAlloc& b) const
847 return static_cast<const DV&>(*this) < static_cast<const DV&>(b);
851 /// Based on operator<
852 template <class DV, class ALLOC>
854 bool DataVectorWithAlloc<DV, ALLOC>::operator> (const DataVectorWithAlloc& b) const
856 return static_cast<const DV&>(*this) > static_cast<const DV&>(b);
860 /// Based on operator<
861 template <class DV, class ALLOC>
863 bool DataVectorWithAlloc<DV, ALLOC>::operator<= (const DataVectorWithAlloc& b) const
865 return static_cast<const DV&>(*this) <= static_cast<const DV&>(b);
869 /// Based on operator<
870 template <class DV, class ALLOC>
872 bool DataVectorWithAlloc<DV, ALLOC>::operator>= (const DataVectorWithAlloc& b) const
874 return static_cast<const DV&>(*this) >= static_cast<const DV&>(b);
879 * @brief Vector equality comparison.
880 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
881 * @return True iff the size and elements of the vectors are equal.
883 * This is an equivalence relation. It is linear in the size of the
884 * vectors. Vectors are considered equivalent if their sizes are equal,
885 * and if corresponding elements compare equal.
887 template <class DV, class ALLOC>
889 bool DataVectorWithAlloc<DV, ALLOC>::operator== (const DataVectorWithAlloc& b) const
891 return static_cast<const DV&>(*this) == static_cast<const DV&>(b);
895 /// Based on operator==
896 template <class DV, class ALLOC>
898 bool DataVectorWithAlloc<DV, ALLOC>::operator!= (const DataVectorWithAlloc& b) const
900 return static_cast<const DV&>(*this) != static_cast<const DV&>(b);
904 //=== Private helpers.
908 * @brief Handle element assignment.
909 * @param pos Position in the container to assign.
910 * @param newElem The new element to assign.
912 * Auxiliary data are copied if appropriate.
914 template <class DV, class ALLOC>
917 DataVectorWithAlloc<DV, ALLOC>::assignElement (typename BaseContainer::iterator pos,
920 newElem.checkHeap (m_heap);
921 DV::assignElement (pos, newElem.release());
926 * @brief Convert a @c DataVectorWithAlloc::iterator to an iterator
927 * of the base @c DataVector.
928 * @param it The @c DataVectorWithAlloc::iterator to convert.
930 template <class DV, class ALLOC>
932 typename DV::iterator
933 DataVectorWithAlloc<DV, ALLOC>::to_base_iterator (iterator it)
935 return typename DV::iterator (it.base(), it.container());
940 * @brief Convert an iterator of the base @c DataVector to
941 * a @c DataVectorWithAlloc::iterator.
942 * @param it The base @c DataVector iterator to convert.
944 template <class DV, class ALLOC>
946 typename DataVectorWithAlloc<DV, ALLOC>::iterator
947 DataVectorWithAlloc<DV, ALLOC>::to_my_iterator (typename DV::iterator it)
949 return iterator (it.base(), this);
954 * @brief Convert an iterator of the base @c vector to
955 * an @c ElementProxy for the @c DataVectorWithAlloc.
956 * @param it The base @c vector iterator to convert.
958 template <class DV, class ALLOC>
960 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
961 DataVectorWithAlloc<DV, ALLOC>::to_element_proxy (typename BaseContainer::iterator i)
963 return ElementProxy (i, this);
967 template <class DV, class ALLOC>
968 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::HeapDeleter (elt_allocator_type&& heap)
969 : m_heap (std::move (heap))
974 template <class DV, class ALLOC>
975 typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
976 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::heap() noexcept
982 template <class DV, class ALLOC>
983 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete (value_type p)
986 using base_value_type_nc = std::remove_const_t<base_value_type>;
987 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (p));
989 m_heap.deallocate (pp, 1);
994 template <class DV, class ALLOC>
995 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete
996 (typename PtrVector::iterator first,
997 typename PtrVector::iterator last)
999 for (; first != last; ++first) {
1001 using base_value_type_nc = std::remove_const_t<base_value_type>;
1002 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (*first));
1003 m_heap.destroy (pp);
1004 m_heap.deallocate (pp, 1);