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 Add an element to the end of the collection.
508 * @param pElem The element to add to the collection.
510 * Note: this method may only be called using the most derived
511 * @c DataVector in the hierarchy.
513 * For @c DataVector, this is like the same as @c push_back, and
514 * it returns the pushed element.
515 * It's included just for interface compatibility with `std::vector`.
517 template <class DV, class ALLOC>
519 typename DataVectorWithAlloc<DV, ALLOC>::value_type
520 DataVectorWithAlloc<DV, ALLOC>::emplace_back (Ptr pElem)
522 return push_back (std::move (pElem));
527 * @brief Add a new element to the collection.
528 * @param position Iterator before which the element will be added.
529 * @param pElem The element to add to the collection.
530 * @return An iterator that points to the inserted data.
532 * The container's ownership policy will determine if it takes ownership
533 * of the new element.
535 * Note: this method may only be called using the most derived
536 * @c DataVector in the hierarchy.
538 template <class DV, class ALLOC>
540 typename DataVectorWithAlloc<DV, ALLOC>::iterator
541 DataVectorWithAlloc<DV, ALLOC>::insert(iterator position, Ptr pElem)
543 pElem.checkHeap (m_heap);
544 return to_my_iterator
545 (DV::insert (to_base_iterator (position), pElem.release()));
550 * @brief Add a new element to the collection.
551 * @param position Iterator before which the element will be added.
552 * @param pElem The element to add to the collection.
553 * @return An iterator that points to the inserted data.
555 * Note: this method may only be called using the most derived
556 * @c DataVector in the hierarchy.
558 * For @c DataVector, this is just the same as @c insert.
559 * It's included just for interface compatibility with `std::vector`.
561 template <class DV, class ALLOC>
563 typename DataVectorWithAlloc<DV, ALLOC>::iterator
564 DataVectorWithAlloc<DV, ALLOC>::emplace(iterator position, Ptr pElem)
566 return this->insert (position, std::move(pElem));
570 //=== Erasure operations.
574 * @brief Remove element at a given position.
575 * @param position Iterator pointing to the element to be removed.
576 * @return An iterator pointing to the next element (or @c end()).
578 * The pointed-to element will be deleted.
580 template <class DV, class ALLOC>
582 typename DataVectorWithAlloc<DV, ALLOC>::iterator
583 DataVectorWithAlloc<DV, ALLOC>::erase(iterator position)
585 return to_my_iterator (DV::erase (to_base_iterator (position)));
590 * @brief Remove a range of elements.
591 * @param first Iterator pointing to the first element to be removed.
592 * @param last Iterator pointing one past the last element to be removed.
593 * @return An iterator pointing to the element pointed to by @a last
594 * prior to erasing (or @c end()).
596 * The removed elements will be deleted.
598 template <class DV, class ALLOC>
600 typename DataVectorWithAlloc<DV, ALLOC>::iterator
601 DataVectorWithAlloc<DV, ALLOC>::erase(iterator first, iterator last)
603 return to_my_iterator
604 (DV::erase (to_base_iterator (first),
605 to_base_iterator (last)));
611 * @brief Erase all the elements in the collection.
613 * The removed elements will be deleted.
615 template <class DV, class ALLOC>
617 void DataVectorWithAlloc<DV, ALLOC>::clear()
627 * @brief Swap this collection with another.
628 * @param rhs The collection with which to swap.
630 * Ownership is swapped along with the collection content.
632 * Note: this method may only be called using the most-derived
633 * @c DataVector in the hierarchy. The @a rhs must also be
634 * referenced using the most-derived @c DataVector.
636 template <class DV, class ALLOC>
638 void DataVectorWithAlloc<DV, ALLOC>::swap (DataVectorWithAlloc& rhs)
641 std::swap (m_heap, rhs.m_heap);
646 * @brief Swap the referents of two @c DataVector iterators.
647 * @param a The first iterator for the swap.
648 * @param b The second iterator for the swap.
650 * The iterators must both refer to the same container.
652 template <class DV, class ALLOC>
654 void DataVectorWithAlloc<DV, ALLOC>::iter_swap (iterator a, iterator b)
656 if (a.container() != b.container()) {
657 throw SG::ExcBadIterSwap();
659 DV::iter_swap (to_base_iterator (a),
660 to_base_iterator (b));
664 //=== Non-standard operations.
668 * @brief Swap one element out of the container.
669 * @param index Index of the element in the container to swap.
670 * @param newElem New element to put in the container.
672 * @param oldElem Reference to receive the element removed from the
675 * Reference @a oldElem is initialized with element @a index of the
676 * collection (no bounds checking). Then element @a index is set
679 * Note: this method may only be called using the most derived
680 * @c DataVector in the hierarchy.
682 template <class DV, class ALLOC>
685 DataVectorWithAlloc<DV, ALLOC>::swapElement (size_type index,
689 newElem.checkHeap (m_heap);
690 typename DV::value_type pnew = newElem.release();
691 typename DV::value_type pold = nullptr;
692 DV::swapElement (index, pnew, pold);
693 oldElem = Ptr (pold, UPDeleter (*m_heap));
698 * @brief Swap one element out of the container.
699 * @param pos The element in the container to swap.
700 * @param newElem New element to put in the container.
702 * @param oldElem Reference to receive the element removed from the
705 * Reference @a oldElem is initialized with element @a pos of the
706 * collection (no bounds checking). Then element @a index is set
709 * Note: this method may only be called using the most derived
710 * @c DataList in the hierarchy.
712 template <class DV, class ALLOC>
715 DataVectorWithAlloc<DV, ALLOC>::swapElement (iterator pos,
719 newElem.checkHeap (m_heap);
720 typename DV::value_type pnew = newElem.release();
721 typename DV::value_type pold = nullptr;
722 DV::swapElement (to_base_iterator(pos), pnew, pold);
723 oldElem = Ptr (pold, UPDeleter (*m_heap));
728 * @brief Return a pointer to this object, as a const @c DataVector.
730 template <class DV, class ALLOC>
733 DataVectorWithAlloc<DV, ALLOC>::asDataVector() const
735 return static_cast<const DV*>(this);
740 * @brief Cast from a @c DataVector to a @c DataVectorWithAlloc.
741 * @param dv Pointer to object to cast.
743 * Return @c DV cast to a @c DataVectorWithAlloc.
745 template <class DV, class ALLOC>
746 const DataVectorWithAlloc<DV, ALLOC>*
747 DataVectorWithAlloc<DV, ALLOC>::fromDataVector (const DV* dv)
749 if (typeid (*dv) == typeid (DataVectorWithAlloc))
750 return static_cast<const DataVectorWithAlloc*> (dv);
756 * @brief Reset indices / reorder aux data after elements have been permuted.
757 * @param beg Start of the range of elements to process.
758 * @param end End of the range of elements to process.
760 template <class DV, class ALLOC>
762 void DataVectorWithAlloc<DV, ALLOC>::resortAux (iterator beg, iterator end)
764 DV::resortAux (to_base_iterator(beg), to_base_iterator(end));
769 * @brief Convert to @c AuxVectorBase.
771 * Needed to get @x AuxVectorBase from a @c DataVectorWithAlloc.
772 * Present in @c DataVector as well for consistency.
774 template <class DV, class ALLOC>
776 const SG::AuxVectorBase& DataVectorWithAlloc<DV, ALLOC>::auxbase() const
783 * @brief Allocate a new vector element.
785 * Arguments will be forwarded to the element constructor.
787 template <class DV, class ALLOC>
788 template <class... Args>
789 typename DataVectorWithAlloc<DV, ALLOC>::Ptr
790 DataVectorWithAlloc<DV, ALLOC>::allocate (Args&&... args)
792 typename elt_allocator_type::pointer p = m_heap->allocate(1);
794 m_heap->construct (p, std::forward<Args>(args)...);
797 m_heap->deallocate (p, 1);
800 return Ptr (p, UPDeleter (*m_heap));
804 //=== Relational operators.
808 * @brief Vector ordering relation.
809 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
810 * @return True iff @a *this is lexicographically less than @a b.
812 * This is a total ordering relation. It is linear in the size of the
813 * vectors. Comparisons are done on the pointer values of the elements.
815 * See @c std::lexicographical_compare() for how the determination is made.
817 template <class DV, class ALLOC>
819 bool DataVectorWithAlloc<DV, ALLOC>::operator< (const DataVectorWithAlloc& b) const
821 return static_cast<const DV&>(*this) < static_cast<const DV&>(b);
825 /// Based on operator<
826 template <class DV, class ALLOC>
828 bool DataVectorWithAlloc<DV, ALLOC>::operator> (const DataVectorWithAlloc& b) const
830 return static_cast<const DV&>(*this) > static_cast<const DV&>(b);
834 /// Based on operator<
835 template <class DV, class ALLOC>
837 bool DataVectorWithAlloc<DV, ALLOC>::operator<= (const DataVectorWithAlloc& b) const
839 return static_cast<const DV&>(*this) <= static_cast<const DV&>(b);
843 /// Based on operator<
844 template <class DV, class ALLOC>
846 bool DataVectorWithAlloc<DV, ALLOC>::operator>= (const DataVectorWithAlloc& b) const
848 return static_cast<const DV&>(*this) >= static_cast<const DV&>(b);
853 * @brief Vector equality comparison.
854 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
855 * @return True iff the size and elements of the vectors are equal.
857 * This is an equivalence relation. It is linear in the size of the
858 * vectors. Vectors are considered equivalent if their sizes are equal,
859 * and if corresponding elements compare equal.
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);
878 //=== Private helpers.
882 * @brief Handle element assignment.
883 * @param pos Position in the container to assign.
884 * @param newElem The new element to assign.
886 * Auxiliary data are copied if appropriate.
888 template <class DV, class ALLOC>
891 DataVectorWithAlloc<DV, ALLOC>::assignElement (typename BaseContainer::iterator pos,
894 newElem.checkHeap (m_heap);
895 DV::assignElement (pos, newElem.release());
900 * @brief Convert a @c DataVectorWithAlloc::iterator to an iterator
901 * of the base @c DataVector.
902 * @param it The @c DataVectorWithAlloc::iterator to convert.
904 template <class DV, class ALLOC>
906 typename DV::iterator
907 DataVectorWithAlloc<DV, ALLOC>::to_base_iterator (iterator it)
909 return typename DV::iterator (it.base(), it.container());
914 * @brief Convert an iterator of the base @c DataVector to
915 * a @c DataVectorWithAlloc::iterator.
916 * @param it The base @c DataVector iterator to convert.
918 template <class DV, class ALLOC>
920 typename DataVectorWithAlloc<DV, ALLOC>::iterator
921 DataVectorWithAlloc<DV, ALLOC>::to_my_iterator (typename DV::iterator it)
923 return iterator (it.base(), this);
928 * @brief Convert an iterator of the base @c vector to
929 * an @c ElementProxy for the @c DataVectorWithAlloc.
930 * @param it The base @c vector iterator to convert.
932 template <class DV, class ALLOC>
934 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
935 DataVectorWithAlloc<DV, ALLOC>::to_element_proxy (typename BaseContainer::iterator i)
937 return ElementProxy (i, this);
941 template <class DV, class ALLOC>
942 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::HeapDeleter (elt_allocator_type&& heap)
943 : m_heap (std::move (heap))
948 template <class DV, class ALLOC>
949 typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
950 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::heap() noexcept
956 template <class DV, class ALLOC>
957 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete (value_type p)
960 using base_value_type_nc = std::remove_const_t<base_value_type>;
961 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (p));
963 m_heap.deallocate (pp, 1);
968 template <class DV, class ALLOC>
969 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete
970 (typename PtrVector::iterator first,
971 typename PtrVector::iterator last)
973 for (; first != last; ++first) {
975 using base_value_type_nc = std::remove_const_t<base_value_type>;
976 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (*first));
978 m_heap.deallocate (pp, 1);