2 * Copyright (C) 2002-2021 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.
15 template <class DV, class ALLOC>
17 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::UPDeleter() noexcept
23 template <class DV, class ALLOC>
25 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::UPDeleter (elt_allocator_type& heap) noexcept
31 template <class DV, class ALLOC>
33 void DataVectorWithAlloc<DV, ALLOC>::UPDeleter::operator() (value_type p)
35 using base_value_type_nc = std::remove_const_t<base_value_type>;
36 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (p));
38 m_heap->deallocate (pp, 1);
42 template <class DV, class ALLOC>
44 const typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type*
45 DataVectorWithAlloc<DV, ALLOC>::UPDeleter::heap() const noexcept
51 template <class DV, class ALLOC>
53 DataVectorWithAlloc<DV, ALLOC>::Ptr::Ptr (std::nullptr_t) noexcept
58 template <class DV, class ALLOC>
60 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator bool() const noexcept
62 return static_cast<bool>(m_ptr);
66 template <class DV, class ALLOC>
68 typename DataVectorWithAlloc<DV, ALLOC>::Ptr&
69 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator= (std::nullptr_t) noexcept
76 template <class DV, class ALLOC>
78 void DataVectorWithAlloc<DV, ALLOC>::Ptr::swap (Ptr& other) noexcept
80 m_ptr.swap (other.m_ptr);
84 template <class DV, class ALLOC>
86 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
87 DataVectorWithAlloc<DV, ALLOC>::Ptr::get() const noexcept
93 template <class DV, class ALLOC>
95 typename std::add_lvalue_reference<typename DV::base_value_type>::type
96 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator*() const
102 template <class DV, class ALLOC>
104 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
105 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator->() const noexcept
111 template <class DV, class ALLOC>
114 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator== (const Ptr& other) const noexcept
116 return m_ptr == other.m_ptr;
120 template <class DV, class ALLOC>
123 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator< (const Ptr& other) const noexcept
125 return m_ptr < other.m_ptr;
129 template <class DV, class ALLOC>
132 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator== (std::nullptr_t) const noexcept
134 return m_ptr == nullptr;
138 template <class DV, class ALLOC>
141 DataVectorWithAlloc<DV, ALLOC>::Ptr::operator!= (std::nullptr_t) const noexcept
143 return m_ptr != nullptr;
147 template <class DV, class ALLOC>
149 DataVectorWithAlloc<DV, ALLOC>::Ptr::Ptr (pointer p, UPDeleter&& d) noexcept
150 : m_ptr (p, std::move(d))
155 template <class DV, class ALLOC>
157 typename DataVectorWithAlloc<DV, ALLOC>::Ptr::pointer
158 DataVectorWithAlloc<DV, ALLOC>::Ptr::release() noexcept
160 return m_ptr.release();
164 template <class DV, class ALLOC>
167 DataVectorWithAlloc<DV, ALLOC>::Ptr::checkHeap (const elt_allocator_type* other_heap) const
169 const elt_allocator_type* this_heap = m_ptr.get_deleter().heap();
170 if (this_heap && this_heap != other_heap) {
171 SG::throwExcAllocOwnership();
176 //=== Constructors, destructors, assignment.
180 * @brief Default constructor.
181 * @param eltAlloc The element allocator.
183 template <class DV, class ALLOC>
184 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
185 (elt_allocator_type&& eltAlloc /*= elt_allocator_type()*/)
187 auto del = std::make_unique<HeapDeleter> (std::move (eltAlloc));
188 m_heap = &del->heap();
189 DV::clear (std::move (del));
194 * @brief Sized constructor.
195 * @param n The size of the container.
196 * @param eltAlloc The element allocator.
198 * Note that unlike the standard vector constructor, you can't specify
199 * an initial value here. The container will be initialized with 0's.
201 template <class DV, class ALLOC>
202 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
204 elt_allocator_type&& eltAlloc /*= elt_allocator_type()*/)
206 auto del = std::make_unique<HeapDeleter> (std::move (eltAlloc));
207 m_heap = &del->heap();
208 DV::clear (std::move (del));
214 * @brief Move constructor.
215 * @param rhs The container from which to move.
217 * Any auxiliary data will be moved along with the container contents.
219 * The existing allocator is moved. @c rhs will be left with a new,
220 * default-initialized, allocator.
222 template <class DV, class ALLOC>
223 DataVectorWithAlloc<DV, ALLOC>::DataVectorWithAlloc
224 (DataVectorWithAlloc&& rhs)
225 : DV (std::move (rhs)),
228 auto del = std::make_unique<HeapDeleter> (elt_allocator_type());
229 rhs.m_heap = &del->heap();
230 static_cast<DV&>(rhs).clear (std::move (del));
235 * @brief Move assignment.
236 * @param rhs The container from which to move.
238 * Any auxiliary data will be moved along with the container contents.
240 * The existing allocator is moved. @c rhs will be left with a new,
241 * default-initialized, allocator.
243 template <class DV, class ALLOC>
244 DataVectorWithAlloc<DV, ALLOC>&
245 DataVectorWithAlloc<DV, ALLOC>::operator= (DataVectorWithAlloc&& rhs)
248 DV::operator= (std::move (rhs));
250 auto del = std::make_unique<HeapDeleter> (elt_allocator_type());
251 rhs.m_heap = &del->heap();
252 static_cast<DV&>(rhs).clear (std::move (del));
261 template <class DV, class ALLOC>
262 DataVectorWithAlloc<DV, ALLOC>::~DataVectorWithAlloc()
264 // If the heap memory was protected, unprotect it now.
265 SG::maybeUnprotect (*m_heap);
270 * @brief Return the underlying allocator.
272 template <class DV, class ALLOC>
274 const typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
275 DataVectorWithAlloc<DV, ALLOC>::elt_allocator() const
282 * @brief Return the underlying allocator.
284 template <class DV, class ALLOC>
286 typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
287 DataVectorWithAlloc<DV, ALLOC>::elt_allocator()
293 //=== Size and capacity.
297 * @fn void reserve (size_type n)
298 * @brief Attempt to preallocate enough memory for a specified number
300 * @param n Number of elements required.
302 template <class DV, class ALLOC>
303 void DataVectorWithAlloc<DV, ALLOC>::reserve (size_type n)
311 * @brief Change the vector capacity to match the current size.
313 * Note: this does not affect auxiliary data.
315 template <class DV, class ALLOC>
316 void DataVectorWithAlloc<DV, ALLOC>::shrink_to_fit()
319 m_heap->reserve (size());
323 //=== Element access.
327 * @brief Access an element, as an lvalue.
328 * @param n Array index to access.
329 * @return Proxy to the element at @a n.
331 * No bounds checking is done.
332 * Note that we return a proxy object rather than a reference;
333 * the proxy will handle deleting an owned element if it's assigned to.
335 template <class DV, class ALLOC>
337 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
338 DataVectorWithAlloc<DV, ALLOC>::operator[] (size_type n)
340 return to_element_proxy (this->m_pCont.begin() + n);
345 * @brief Access an element, as an lvalue.
346 * @param n Array index to access.
347 * @return Proxy to the element at @a n.
349 * Will raise @c std::out_of_range if the index is out-of-bounds.
350 * Note that we return a proxy object rather than a reference;
351 * the proxy will handle deleting an owned element if it's assigned to.
353 template <class DV, class ALLOC>
355 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
356 DataVectorWithAlloc<DV, ALLOC>::at (size_type n)
358 if (n >= this->size())
359 throw std::out_of_range ("DataVector::at range check");
360 return to_element_proxy (this->m_pCont.begin() + n);
365 * @brief Access the first element in the collection as an lvalue.
366 * @return Proxy to the first element in the collection.
368 * No checking is done to ensure that the container is not empty.
369 * Note that we return a proxy object rather than a reference;
370 * the proxy will handle deleting an owned element if it's assigned to.
372 template <class DV, class ALLOC>
374 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
375 DataVectorWithAlloc<DV, ALLOC>::front ()
377 return to_element_proxy (this->m_pCont.begin());
382 * @brief Access the last element in the collection as an lvalue.
383 * @return Proxy to the last element in the collection.
385 * No checking is done to ensure that the container is not empty.
386 * Note that we return a proxy object rather than a reference;
387 * the proxy will handle deleting an owned element if it's assigned to.
389 template <class DV, class ALLOC>
391 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
392 DataVectorWithAlloc<DV, ALLOC>::back ()
394 return to_element_proxy (this->m_pCont.end()-1);
398 //=== Iterator creation.
402 * @brief Return an @c iterator pointing at the beginning
404 * @return An @c iterator.
406 * Note that dereferencing the iterator will yield a proxy rather
407 * than a reference; the proxy will handle deleting an owned element
408 * if it's assigned to.
410 template <class DV, class ALLOC>
412 typename DataVectorWithAlloc<DV, ALLOC>::iterator
413 DataVectorWithAlloc<DV, ALLOC>::begin() noexcept
415 return to_my_iterator (DV::begin());
420 * @brief Return an @c iterator pointing past the end
422 * @return An @c iterator.
424 * Note that dereferencing the iterator will yield a proxy rather
425 * than a reference; the proxy will handle deleting an owned element
426 * if it's assigned to.
428 template <class DV, class ALLOC>
430 typename DataVectorWithAlloc<DV, ALLOC>::iterator
431 DataVectorWithAlloc<DV, ALLOC>::end() noexcept
433 return to_my_iterator (DV::end());
438 * @brief Return a @c reverse_iterator pointing past the end
440 * @return A @c reverse_iterator.
442 * Note that dereferencing the iterator will yield a proxy rather
443 * than a reference; the proxy will handle deleting an owned element
444 * if it's assigned to.
446 template <class DV, class ALLOC>
448 typename DataVectorWithAlloc<DV, ALLOC>::reverse_iterator
449 DataVectorWithAlloc<DV, ALLOC>::rbegin() noexcept
451 return reverse_iterator (to_my_iterator (DV::end()));
456 * @brief Return a @c reverse_iterator pointing at the beginning
458 * @return A @c reverse_iterator.
460 * Note that dereferencing the iterator will yield a proxy rather
461 * than a reference; the proxy will handle deleting an owned element
462 * if it's assigned to.
464 template <class DV, class ALLOC>
466 typename DataVectorWithAlloc<DV, ALLOC>::reverse_iterator
467 DataVectorWithAlloc<DV, ALLOC>::rend() noexcept
469 return reverse_iterator (to_my_iterator (DV::begin()));
473 //=== Insertion operations.
477 * @brief Add an element to the end of the collection.
478 * @param pElem The element to add to the collection.
480 * Note: this method may only be called using the most derived
481 * @c DataVector in the hierarchy.
483 * Returns the pushed pointer.
485 template <class DV, class ALLOC>
487 typename DataVectorWithAlloc<DV, ALLOC>::value_type
488 DataVectorWithAlloc<DV, ALLOC>::push_back (Ptr pElem)
490 pElem.checkHeap (m_heap);
491 typename DV::value_type p = pElem.release();
498 * @brief Add an element to the end of the collection.
499 * @param pElem The element to add to the collection.
501 * Note: this method may only be called using the most derived
502 * @c DataVector in the hierarchy.
504 * For @c DataVector, this is like the same as @c push_back, and
505 * it returns the pushed element.
506 * It's included just for interface compatibility with `std::vector`.
508 template <class DV, class ALLOC>
510 typename DataVectorWithAlloc<DV, ALLOC>::value_type
511 DataVectorWithAlloc<DV, ALLOC>::emplace_back (Ptr pElem)
513 return push_back (std::move (pElem));
518 * @brief Add a new element to the collection.
519 * @param position Iterator before which the element will be added.
520 * @param pElem The element to add to the collection.
521 * @return An iterator that points to the inserted data.
523 * The container's ownership policy will determine if it takes ownership
524 * of the new element.
526 * Note: this method may only be called using the most derived
527 * @c DataVector in the hierarchy.
529 template <class DV, class ALLOC>
531 typename DataVectorWithAlloc<DV, ALLOC>::iterator
532 DataVectorWithAlloc<DV, ALLOC>::insert(iterator position, Ptr pElem)
534 pElem.checkHeap (m_heap);
535 return to_my_iterator
536 (DV::insert (to_base_iterator (position), pElem.release()));
541 * @brief Add a new element to the collection.
542 * @param position Iterator before which the element will be added.
543 * @param pElem The element to add to the collection.
544 * @return An iterator that points to the inserted data.
546 * Note: this method may only be called using the most derived
547 * @c DataVector in the hierarchy.
549 * For @c DataVector, this is just the same as @c insert.
550 * It's included just for interface compatibility with `std::vector`.
552 template <class DV, class ALLOC>
554 typename DataVectorWithAlloc<DV, ALLOC>::iterator
555 DataVectorWithAlloc<DV, ALLOC>::emplace(iterator position, Ptr pElem)
557 return this->insert (position, std::move(pElem));
561 //=== Erasure operations.
565 * @brief Remove element at a given position.
566 * @param position Iterator pointing to the element to be removed.
567 * @return An iterator pointing to the next element (or @c end()).
569 * The pointed-to element will be deleted.
571 template <class DV, class ALLOC>
573 typename DataVectorWithAlloc<DV, ALLOC>::iterator
574 DataVectorWithAlloc<DV, ALLOC>::erase(iterator position)
576 return to_my_iterator (DV::erase (to_base_iterator (position)));
581 * @brief Remove a range of elements.
582 * @param first Iterator pointing to the first element to be removed.
583 * @param last Iterator pointing one past the last element to be removed.
584 * @return An iterator pointing to the element pointed to by @a last
585 * prior to erasing (or @c end()).
587 * The removed elements will be deleted.
589 template <class DV, class ALLOC>
591 typename DataVectorWithAlloc<DV, ALLOC>::iterator
592 DataVectorWithAlloc<DV, ALLOC>::erase(iterator first, iterator last)
594 return to_my_iterator
595 (DV::erase (to_base_iterator (first),
596 to_base_iterator (last)));
602 * @brief Erase all the elements in the collection.
604 * The removed elements will be deleted.
606 template <class DV, class ALLOC>
608 void DataVectorWithAlloc<DV, ALLOC>::clear()
618 * @brief Swap this collection with another.
619 * @param rhs The collection with which to swap.
621 * Ownership is swapped along with the collection content.
623 * Note: this method may only be called using the most-derived
624 * @c DataVector in the hierarchy. The @a rhs must also be
625 * referenced using the most-derived @c DataVector.
627 template <class DV, class ALLOC>
629 void DataVectorWithAlloc<DV, ALLOC>::swap (DataVectorWithAlloc& rhs)
632 std::swap (m_heap, rhs.m_heap);
637 * @brief Swap the referents of two @c DataVector iterators.
638 * @param a The first iterator for the swap.
639 * @param b The second iterator for the swap.
641 * The iterators must both refer to the same container.
643 template <class DV, class ALLOC>
645 void DataVectorWithAlloc<DV, ALLOC>::iter_swap (iterator a, iterator b)
647 if (a.container() != b.container()) {
648 throw SG::ExcBadIterSwap();
650 DV::iter_swap (to_base_iterator (a),
651 to_base_iterator (b));
655 //=== Non-standard operations.
659 * @brief Swap one element out of the container.
660 * @param index Index of the element in the container to swap.
661 * @param newElem New element to put in the container.
663 * @param oldElem Reference to receive the element removed from the
666 * Reference @a oldElem is initialized with element @a index of the
667 * collection (no bounds checking). Then element @a index is set
670 * Note: this method may only be called using the most derived
671 * @c DataVector in the hierarchy.
673 template <class DV, class ALLOC>
676 DataVectorWithAlloc<DV, ALLOC>::swapElement (size_type index,
680 newElem.checkHeap (m_heap);
681 typename DV::value_type pnew = newElem.release();
682 typename DV::value_type pold = nullptr;
683 DV::swapElement (index, pnew, pold);
684 oldElem = Ptr (pold, UPDeleter (*m_heap));
689 * @brief Swap one element out of the container.
690 * @param pos The element in the container to swap.
691 * @param newElem New element to put in the container.
693 * @param oldElem Reference to receive the element removed from the
696 * Reference @a oldElem is initialized with element @a pos of the
697 * collection (no bounds checking). Then element @a index is set
700 * Note: this method may only be called using the most derived
701 * @c DataList in the hierarchy.
703 template <class DV, class ALLOC>
706 DataVectorWithAlloc<DV, ALLOC>::swapElement (iterator pos,
710 newElem.checkHeap (m_heap);
711 typename DV::value_type pnew = newElem.release();
712 typename DV::value_type pold = nullptr;
713 DV::swapElement (to_base_iterator(pos), pnew, pold);
714 oldElem = Ptr (pold, UPDeleter (*m_heap));
719 * @brief Return a pointer to this object, as a const @c DataVector.
721 template <class DV, class ALLOC>
724 DataVectorWithAlloc<DV, ALLOC>::asDataVector() const
726 return static_cast<const DV*>(this);
731 * @brief Cast from a @c DataVector to a @c DataVectorWithAlloc.
732 * @param dv Pointer to object to cast.
734 * Return @c DV cast to a @c DataVectorWithAlloc.
736 template <class DV, class ALLOC>
737 const DataVectorWithAlloc<DV, ALLOC>*
738 DataVectorWithAlloc<DV, ALLOC>::fromDataVector (const DV* dv)
740 if (typeid (*dv) == typeid (DataVectorWithAlloc))
741 return static_cast<const DataVectorWithAlloc*> (dv);
747 * @brief Reset indices / reorder aux data after elements have been permuted.
748 * @param beg Start of the range of elements to process.
749 * @param end End of the range of elements to process.
751 template <class DV, class ALLOC>
753 void DataVectorWithAlloc<DV, ALLOC>::resortAux (iterator beg, iterator end)
755 DV::resortAux (to_base_iterator(beg), to_base_iterator(end));
760 * @brief Convert to @c AuxVectorBase.
762 * Needed to get @x AuxVectorBase from a @c DataVectorWithAlloc.
763 * Present in @c DataVector as well for consistency.
765 template <class DV, class ALLOC>
767 const SG::AuxVectorBase& DataVectorWithAlloc<DV, ALLOC>::auxbase() const
774 * @brief Allocate a new vector element.
776 * Arguments will be forwarded to the element constructor.
778 template <class DV, class ALLOC>
779 template <class... Args>
780 typename DataVectorWithAlloc<DV, ALLOC>::Ptr
781 DataVectorWithAlloc<DV, ALLOC>::allocate (Args&&... args)
783 typename elt_allocator_type::pointer p = m_heap->allocate(1);
785 m_heap->construct (p, std::forward<Args>(args)...);
788 m_heap->deallocate (p, 1);
791 return Ptr (p, UPDeleter (*m_heap));
795 //=== Relational operators.
799 * @brief Vector ordering relation.
800 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
801 * @return True iff @a *this is lexicographically less than @a b.
803 * This is a total ordering relation. It is linear in the size of the
804 * vectors. Comparisons are done on the pointer values of the elements.
806 * See @c std::lexicographical_compare() for how the determination is made.
808 template <class DV, class ALLOC>
810 bool DataVectorWithAlloc<DV, ALLOC>::operator< (const DataVectorWithAlloc& b) const
812 return static_cast<const DV&>(*this) < static_cast<const DV&>(b);
816 /// Based on operator<
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);
844 * @brief Vector equality comparison.
845 * @param b A @c DataVectorWithAlloc of the same type as @a *this.
846 * @return True iff the size and elements of the vectors are equal.
848 * This is an equivalence relation. It is linear in the size of the
849 * vectors. Vectors are considered equivalent if their sizes are equal,
850 * and if corresponding elements compare equal.
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 //=== Private helpers.
873 * @brief Handle element assignment.
874 * @param pos Position in the container to assign.
875 * @param newElem The new element to assign.
877 * Auxiliary data are copied if appropriate.
879 template <class DV, class ALLOC>
882 DataVectorWithAlloc<DV, ALLOC>::assignElement (typename BaseContainer::iterator pos,
885 newElem.checkHeap (m_heap);
886 DV::assignElement (pos, newElem.release());
891 * @brief Convert a @c DataVectorWithAlloc::iterator to an iterator
892 * of the base @c DataVector.
893 * @param it The @c DataVectorWithAlloc::iterator to convert.
895 template <class DV, class ALLOC>
897 typename DV::iterator
898 DataVectorWithAlloc<DV, ALLOC>::to_base_iterator (iterator it)
900 return typename DV::iterator (it.base(), it.container());
905 * @brief Convert an iterator of the base @c DataVector to
906 * a @c DataVectorWithAlloc::iterator.
907 * @param it The base @c DataVector iterator to convert.
909 template <class DV, class ALLOC>
911 typename DataVectorWithAlloc<DV, ALLOC>::iterator
912 DataVectorWithAlloc<DV, ALLOC>::to_my_iterator (typename DV::iterator it)
914 return iterator (it.base(), this);
919 * @brief Convert an iterator of the base @c vector to
920 * an @c ElementProxy for the @c DataVectorWithAlloc.
921 * @param it The base @c vector iterator to convert.
923 template <class DV, class ALLOC>
925 typename DataVectorWithAlloc<DV, ALLOC>::ElementProxy
926 DataVectorWithAlloc<DV, ALLOC>::to_element_proxy (typename BaseContainer::iterator i)
928 return ElementProxy (i, this);
932 template <class DV, class ALLOC>
933 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::HeapDeleter (elt_allocator_type&& heap)
934 : m_heap (std::move (heap))
939 template <class DV, class ALLOC>
940 typename DataVectorWithAlloc<DV, ALLOC>::elt_allocator_type&
941 DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::heap() noexcept
947 template <class DV, class ALLOC>
948 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete (value_type p)
951 using base_value_type_nc = std::remove_const_t<base_value_type>;
952 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (p));
954 m_heap.deallocate (pp, 1);
959 template <class DV, class ALLOC>
960 void DataVectorWithAlloc<DV, ALLOC>::HeapDeleter::doDelete
961 (typename PtrVector::iterator first,
962 typename PtrVector::iterator last)
964 for (; first != last; ++first) {
966 using base_value_type_nc = std::remove_const_t<base_value_type>;
967 base_value_type_nc* pp ATLAS_THREAD_SAFE = const_cast<base_value_type_nc*>(DV::do_cast_nc (*first));
969 m_heap.deallocate (pp, 1);