ATLAS Offline Software
Loading...
Searching...
No Matches
DataVector.icc
Go to the documentation of this file.
1// Dear emacs, this is -*- c++ -*-
2
3/*
4 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5*/
6/**
7 * @file AthContainers/DataVector.icc
8 * @author scott snyder, Paolo Calafiura, etc
9 * @date May 2005; rewritten from earlier version.
10 * @brief An STL vector of pointers that by default owns its pointed-to
11 * elements.
12 * Implementation file.
13 */
14
15
16#include "AthContainers/tools/CompareAndPrint.h"
17#include "AthContainers/tools/ATHCONTAINERS_ASSERT.h"
18#include "CxxUtils/releasing_iterator.h"
19#include "CxxUtils/throw_out_of_range.h"
20#include <limits>
21#include <functional>
22
23
24//****************************************************************************
25// VirtBases
26//
27
28namespace ROOT { namespace Meta { namespace Selection {
29 namespace DataVector_detail {
30 template <class B1, class B2, class B3> class VirtBases;
31 }
32}}} // ROOT namespace
33
34
35namespace DataVector_detail {
36
37/* #define DO_REMOVE_DUPLICATES to activate for debugging purposes (Slow) */
38// Note: this name should be distinct from the corresponding one in DataList,
39// even though they're in different namespaces. This due to an apparent
40// Koenig lookup bug in gccxml 0.9.0.
41template <class FI>
42void optimizeMeAway_DV(FI, bool){}
43/**
44 * @brief Remove duplicates from a @c DataVector before deleting elements.
45 * @param b Start of range to scan.
46 * @param e One past end of range to scan.
47 * @param quiet If true, complain if duplicates are found.
48 * @return One past the last unique elements.
49 *
50 * The elements within the range are sorted, then duplicate elements
51 * are moved to the end. If duplicate elements are found and
52 * @a quiet is @c true, then a complaint will be printed.
53 */
54template <class ForwIter>
55ForwIter remove_duplicates(ForwIter b, ForwIter e, bool quiet=false)
56{
57#ifdef DO_REMOVE_DUPLICATES
58 std::sort(b, e);
59 return std::unique(b, e, DataModel_detail::CompareAndPrint(quiet));
60#else
61 optimizeMeAway_DV(b, quiet);
62 return e;
63#endif
64}
65
66/**
67 * @brief VirtBases for one class.
68 *
69 * @c DataVector<T> derives from this for the case of
70 * @c T deriving virtually from a single class.
71 * It in turn derives from @c B1.
72 */
73template <class B1>
74struct VirtBases<B1, DataModel_detail::NoBase, DataModel_detail::NoBase>
75 : virtual public DataVector<B1>
76{
77 // Make these types available to the derived @c DataVector.
78 typedef typename DataVector<B1>::PtrVector PtrVector;
79 typedef typename DataVector<B1>::size_type size_type;
80 typedef typename DataVector<B1>::difference_type difference_type;
81 typedef typename DataVector<B1>::allocator_type allocator_type;
82 typedef typename DataVector<B1>::Deleter Deleter;
83 // cppcheck-suppress duplInheritedMember; deliberate
84 static constexpr bool must_own = DataVector<B1>::must_own;
85
86 // We're using virtual derivation.
87 // cppcheck-suppress duplInheritedMember; deliberate
88 static constexpr bool has_virtual = true;
89
90 // We need to delete the move ctor; otherwise, we get warnings about
91 // a virtual base having a non-trivial move ctor. Then we also need
92 // to explicitly default the ordinary ctors so that they remain visible.
93 VirtBases () = default;
94 VirtBases (const VirtBases&) = default;
95 // default doesn't work here with gcc 4.7; it does with 4.9.
96 VirtBases& operator= (VirtBases&) { return *this; }
97 VirtBases& operator= (VirtBases&&) = delete;
98
99
100protected:
101 // Pass this down to base classes.
102 void clearMostDerived()
103 {
104 DataVector<B1>::clearMostDerived();
105 }
106
107 // We need these here to prevent ambiguities,
108 // but they shouldn't actually be called.
109 virtual const std::type_info& dv_typeid() const override
110 {
111 return typeid(VirtBases);
112 }
113 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
114 {
115 return DataVector<B1>::dvlinfo();
116 }
117 virtual void setMostDerived() override
118 {
119 std::abort();
120 }
121
122
123 static
124 int baseOffset1 (const char* p, const VirtBases& dv,
125 const std::type_info& ti)
126 {
127 return DataVector<B1>::baseOffset1 (p, dv, ti);
128 }
129
130
131private:
132 typedef typename
133 ROOT::Meta::Selection::
134 DataVector_detail::VirtBases<B1,
135 DataModel_detail::NoBase,
136 DataModel_detail::NoBase>::self self;
137};
138
139
140/**
141 * @brief VirtBases for two classes.
142 *
143 * @c DataVector<T> derives from this for the case of
144 * @c T deriving from two classes.
145 * It in turn derives from @c B1 and @c B2.
146 */
147template <class B1, class B2>
148struct VirtBases<B1, B2, DataModel_detail::NoBase>
149 : virtual public DataVector<B1>,
150 virtual public DataVector<B2>
151{
152 // Check to be sure that @c B1 and @c B2 have the same ultimate base type.
153 static_assert (std::is_same_v<typename DataVector<B1>::PtrVector,
154 typename DataVector<B2>::PtrVector>);
155
156 // Make these types available to the derived @c DataVector.
157 typedef typename DataVector<B1>::PtrVector PtrVector;
158 typedef typename DataVector<B1>::size_type size_type;
159 typedef typename DataVector<B1>::difference_type difference_type;
160 typedef typename DataVector<B1>::allocator_type allocator_type;
161 typedef typename DataVector<B1>::Deleter Deleter;
162 // cppcheck-suppress duplInheritedMember; deliberate
163 static constexpr bool must_own = DataVector<B1>::must_own;
164
165 // We're using virtual derivation.
166 // cppcheck-suppress duplInheritedMember; deliberate
167 static constexpr bool has_virtual = true;
168
169
170 // We need to delete the move ctor; otherwise, we get warnings about
171 // a virtual base having a non-trivial move ctor. Then we also need
172 // to explicitly default the ordinary ctors so that they remain visible.
173 VirtBases () = default;
174 VirtBases (const VirtBases&) = default;
175 // default doesn't work here with gcc 4.7; it does with 4.9.
176 VirtBases& operator= (VirtBases&) { return *this; }
177 VirtBases& operator= (VirtBases&&) = delete;
178
179
180protected:
181 // Pass this down to base classes.
182 void clearMostDerived()
183 {
184 DataVector<B1>::clearMostDerived();
185 DataVector<B2>::clearMostDerived();
186 }
187
188 // We need these here to prevent ambiguities,
189 // but they shouldn't actually be called.
190 virtual const std::type_info& dv_typeid() const override
191 {
192 return typeid(VirtBases);
193 }
194 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
195 {
196 return DataVector<B1>::dvlinfo();
197 }
198 virtual void setMostDerived() override
199 {
200 std::abort();
201 }
202
203
204 static
205 int baseOffset1 (const char* p, const VirtBases& dv,
206 const std::type_info& ti)
207 {
208 int ret = DataVector<B1>::baseOffset1 (p, dv, ti);
209 if (ret >= 0)
210 return ret;
211 return DataVector<B2>::baseOffset1 (p, dv, ti);
212 }
213
214
215private:
216 typedef typename
217 ROOT::Meta::Selection::
218 DataVector_detail::VirtBases<B1, B2,
219 DataModel_detail::NoBase>::self self;
220};
221
222
223/**
224 * @brief VirtBases for three classes.
225 *
226 * @c DataVector<T> derives from this for the case of
227 * @c T deriving from three classes.
228 * It in turn derives from @c B1, @c B2, and @c B3.
229 */
230template <class B1, class B2, class B3>
231struct VirtBases
232 : virtual public DataVector<B1>,
233 virtual public DataVector<B2>,
234 virtual public DataVector<B3>
235{
236 // Check to be sure that @c B1, @c B2, and @c B3 have the same
237 // ultimate base type.
238 static_assert (std::is_same_v<typename DataVector<B1>::PtrVector,
239 typename DataVector<B2>::PtrVector>);
240 static_assert (std::is_same_v<typename DataVector<B1>::PtrVector,
241 typename DataVector<B3>::PtrVector>);
242
243
244 // Make these types available to the derived @c DataVector.
245 typedef typename DataVector<B1>::PtrVector PtrVector;
246 typedef typename DataVector<B1>::size_type size_type;
247 typedef typename DataVector<B1>::difference_type difference_type;
248 typedef typename DataVector<B1>::allocator_type allocator_type;
249 typedef typename DataVector<B1>::Deleter Deleter;
250 // cppcheck-suppress duplInheritedMember; deliberate
251 static constexpr bool must_own = DataVector<B1>::must_own;
252
253 // We're using virtual derivation.
254 // cppcheck-suppress duplInheritedMember; deliberate
255 static constexpr bool has_virtual = true;
256
257
258 // We need to delete the move ctor; otherwise, we get warnings about
259 // a virtual base having a non-trivial move ctor. Then we also need
260 // to explicitly default the ordinary ctors so that they remain visible.
261 VirtBases () = default;
262 VirtBases (const VirtBases&) = default;
263 // default doesn't work here with gcc 4.7; it does with 4.9.
264 VirtBases& operator= (VirtBases&) { return *this; }
265 VirtBases& operator= (VirtBases&&) = delete;
266
267
268protected:
269 // Pass this down to base classes.
270 void clearMostDerived()
271 {
272 DataVector<B1>::clearMostDerived();
273 DataVector<B2>::clearMostDerived();
274 DataVector<B3>::clearMostDerived();
275 }
276
277 // We need these here to prevent ambiguities,
278 // but they shouldn't actually be called.
279 virtual const std::type_info& dv_typeid() const override
280 {
281 return typeid(VirtBases);
282 }
283 virtual const DataModel_detail::DVLInfoBase& dvlinfo_v() const override
284 {
285 return DataVector<B1>::dvlinfo();
286 }
287 virtual void setMostDerived() override
288 {
289 std::abort();
290 }
291
292
293 static
294 int baseOffset1 (const char* p, const VirtBases& dv,
295 const std::type_info& ti)
296 {
297 int ret = DataVector<B1>::baseOffset1 (p, dv, ti);
298 if (ret >= 0)
299 return ret;
300 ret = DataVector<B2>::baseOffset1 (p, dv, ti);
301 if (ret >= 0)
302 return ret;
303 return DataVector<B3>::baseOffset1 (p, dv, ti);
304 }
305
306
307private:
308 typedef typename
309 ROOT::Meta::Selection::DataVector_detail::VirtBases<B1, B2, B3>::self
310 self;
311};
312
313
314} // namespace DataVector_detail
315
316
317namespace ROOT { namespace Meta { namespace Selection {
318namespace DataVector_detail {
319
320template< class B1, class B2, class B3 >
321class VirtBases : KeepFirstTemplateArguments< 1 >, SelectNoInstance
322{
323
324public:
325 /// A helper typedef
326 typedef DataVector_detail::VirtBases< B1, B2, B3 > self;
327
328};
329
330}
331}}} // ROOT namespace
332
333
334//****************************************************************************
335// Generic (derived) DataVector implementation.
336//
337
338
339//=== Constructors, destructors, assignment.
340
341
342/**
343 * @brief Default constructor.
344 * @param ownPolicy The ownership mode for the container.
345 * @param trackIndices The index tracking policy.
346 *
347 * By default, a @c DataVector will own its elements.
348 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
349 *
350 * Note that we do the complete initialization here in the derived class,
351 * using the default constructors for the base classes. The reason
352 * for this is to be able to deal nicely with the virtual derivation
353 * case. We can arrange to call the proper base class from here to get
354 * things initialized in the virtual derivation case. But then anyone
355 * who derives from us must also know to explicitly reference that base
356 * class. Doing the initialization explicitly here means that other classes
357 * who derive from us need only know about the most derived DataVector
358 * class.
359 */
360template <class T, class BASE>
361inline
362DataVector<T, BASE>::DataVector
363 (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
364 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
365{
366 this->m_ownPolicy = ownPolicy;
367 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
368 this->m_isMostDerived = true;
369 BASE::clearMostDerived();
370}
371
372
373/**
374 * @brief Sized constructor.
375 * @param n The size of the container.
376 * @param ownPolicy The ownership mode for the container.
377 * @param trackIndices The index tracking policy.
378 *
379 * Note that unlike the standard vector constructor, you can't specify
380 * an initial value here. The container will be initialized with 0's.
381 *
382 * By default, a @c DataVector will own its elements.
383 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
384 *
385 * Note that we do the complete initialization here in the derived class,
386 * using the default constructors for the base classes. The reason
387 * for this is to be able to deal nicely with the virtual derivation
388 * case. We can arrange to call the proper base class from here to get
389 * things initialized in the virtual derivation case. But then anyone
390 * who derives from us must also know to explicitly reference that base
391 * class. Doing the initialization explicitly here means that other classes
392 * who derive from us need only know about the most derived DataVector
393 * class.
394 */
395template <class T, class BASE>
396inline
397DataVector<T, BASE>::DataVector
398 (size_type n,
399 SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
400 SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
401{
402 this->m_ownPolicy = ownPolicy;
403 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
404 this->m_isMostDerived = true;
405 BASE::clearMostDerived();
406 this->m_pCont.resize (n);
407}
408
409
410/**
411 * @brief Move constructor.
412 * @param rhs The container from which to move.
413 *
414 * Any auxiliary data will be moved along with the container contents.
415 */
416template <class T, class BASE>
417DataVector<T, BASE>::DataVector (DataVector&& rhs) noexcept
418{
419 SG::AuxVectorBase::operator= (std::move (rhs));
420 this->m_ownPolicy = rhs.m_ownPolicy;
421 this->m_pCont = std::move (rhs.m_pCont);
422 this->m_deleter = std::move(rhs.m_deleter);
423 rhs.m_deleter = nullptr;
424
425 // Need to reset the container pointer on elements.
426 this->setIndices (this->begin(), this->end());
427 this->m_isMostDerived = true;
428}
429
430
431/**
432 * @brief Constructor from iterators.
433 * @param first The start of the range to put in the new container.
434 * @param last The end of the range to put in the new container.
435 * @param ownPolicy The ownership mode for the container.
436 * @param trackIndices The index tracking policy.
437 * @param store An associated auxiliary data store.
438 *
439 * By default, a view container is made, which does not own its elements.
440 * To have the container take ownership of the pointers passed
441 * to this constructor, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
442 *
443 * Note that we do the complete initialization here in the derived class,
444 * using the default constructors for the base classes. The reason
445 * for this is to be able to deal nicely with the virtual derivation
446 * case. We can arrange to call the proper base class from here to get
447 * things initialized in the virtual derivation case. But then anyone
448 * who derives from us must also know to explicitly reference that base
449 * class. Doing the initialization explicitly here means that other classes
450 * who derive from us need only know about the most derived DataVector
451 * class.
452 */
453template <class T, class BASE>
454template <class InputIterator>
455inline
456DataVector<T, BASE>::DataVector
457 (InputIterator first,
458 InputIterator last,
459 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
460 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_INDEX_TRACKING*/,
461 SG::IAuxStore* store /*= 0*/)
462{
463 // Make sure that the input iterator can actually be converted
464 // to a T*. Lets us give a compilation error for this:
465 // DATAVECTOR_BASE(D, B);
466 // B* bb[] = ...
467 // DataVector<D> d (bb, bb+1);
468 // which would otherwise compile.
469 //FIXME: Rewrite using concepts once we're using c++20.
470 using ittype = typename std::iterator_traits<InputIterator>::value_type;
471 static_assert (std::is_convertible_v<ittype, const T*> ||
472 std::is_convertible_v<ittype, std::unique_ptr<T> >);
473
474 this->m_ownPolicy = ownPolicy;
475 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
476 this->m_isMostDerived = true;
477 BASE::clearMostDerived();
478 if (store)
479 this->setStore (store);
480 insert (this->begin(), first, last);
481}
482
483
484/**
485 * @brief Constructor from an initializer list.
486 * @param l An initializer list.
487 * @param ownPolicy The ownership mode for the container.
488 * @param trackIndices The index tracking policy.
489 * @param store An associated auxiliary data store.
490 *
491 *
492 * A @c DataVector constructed this way will *not* own its elements
493 * by default. To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
494 *
495 * Note that we do the complete initialization here in the derived class,
496 * using the default constructors for the base classes. The reason
497 * for this is to be able to deal nicely with the virtual derivation
498 * case. We can arrange to call the proper base class from here to get
499 * things initialized in the virtual derivation case. But then anyone
500 * who derives from us must also know to explicitly reference that base
501 * class. Doing the initialization explicitly here means that other classes
502 * who derive from us need only know about the most derived DataVector
503 * class.
504 */
505template <class T, class BASE>
506inline
507DataVector<T, BASE>::DataVector
508 (std::initializer_list<value_type> l,
509 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
510 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_INDEX_TRACKING*/,
511 SG::IAuxStore* store /*= 0*/)
512 : DataVector (l.begin(), l.end(), ownPolicy, trackIndices, store)
513{
514}
515
516
517/**
518 * @brief Assignment operator.
519 * @param rhs The DataVector from which to assign.
520 * @return This object.
521 *
522 * This is a `shallow' copy; after the completion of this, the DataVector
523 * will not own its elements. Any elements it owned prior to this call
524 * will be released.
525 *
526 * Note: this method may only be called using the most derived
527 * @c DataVector in the hierarchy.
528 */
529template <class T, class BASE>
530inline
531DataVector<T, BASE>& DataVector<T, BASE>::operator= (const DataVector& rhs)
532{
533 if (&rhs != this) {
534 // Ensure we're not being called via a base class.
535 testInsert ("assignment operator");
536 this->clear(); // Release any currently-owned elements.
537 this->m_ownPolicy = SG::VIEW_ELEMENTS;
538 this->setStore ((SG::IConstAuxStore*)0);
539 this->template initAuxVectorBase<DataVector>(this->m_ownPolicy,
540 SG::DEFAULT_TRACK_INDICES);
541 this->m_pCont = rhs.m_pCont;
542 }
543 return *this;
544}
545
546
547/**
548 * @brief Move assignment.
549 * @param rhs The container from which to move.
550 *
551 * Any auxiliary data will be moved along with the container contents.
552 *
553 * (Can't be noexcept because testInsert() can throw.)
554 */
555template <class T, class BASE>
556DataVector<T, BASE>&
557DataVector<T, BASE>::operator= (DataVector<T, BASE>&& rhs)
558{
559 if (this != &rhs) {
560 // Ensure we're not being called via a base class.
561 testInsert ("assignment operator");
562
563 this->clear(); // Release any currently-owned elements.
564
565 SG::AuxVectorBase::operator= (std::move (rhs));
566 this->m_ownPolicy = rhs.m_ownPolicy;
567 this->m_pCont = std::move (rhs.m_pCont);
568
569 delete this->m_deleter;
570 this->m_deleter = std::move(rhs.m_deleter);
571 rhs.m_deleter = nullptr;
572
573 // Need to reset the container pointer on elements.
574 this->setIndices (this->begin(), this->end());
575 }
576 return *this;
577}
578
579
580/**
581 * @brief Assignment operator, from an initializer list.
582 * @param l An initializer list.
583 * @return This object.
584 *
585 * This is equivalent to @c assign.
586 * Any existing owned elements will be released.
587 * The @c DataVector's ownership policy determines whether it will take
588 * ownership of the new elements.
589 */
590template <class T, class BASE>
591inline
592DataVector<T, BASE>&
593DataVector<T, BASE>::operator= (std::initializer_list<value_type> l)
594{
595 this->assign (l.begin(), l.end());
596 return *this;
597}
598
599
600/**
601 * @brief Assign from iterators.
602 * @param first The start of the range to put in the container.
603 * @param last The end of the range to put in the container.
604 *
605 * Any existing owned elements will be released.
606 * The @c DataVector's ownership policy determines whether it will take
607 * ownership of the new elements.
608 */
609template <class T, class BASE>
610template <class InputIterator>
611void DataVector<T, BASE>::assign(InputIterator first, InputIterator last)
612{
613 // Ensure we're not being called via a base class.
614 testInsert ("assign");
615 this->clear(); // Release any currently-owned elements.
616 insert(begin(), first, last);
617}
618
619
620/**
621 * @brief Assign from an initializer list.
622 * @param l An initializer list.
623 *
624 * Any existing owned elements will be released.
625 * The @c DataVector's ownership policy determines whether it will take
626 * ownership of the new elements.
627 */
628template <class T, class BASE>
629void DataVector<T, BASE>::assign(std::initializer_list<value_type> l)
630{
631 this->assign (l.begin(), l.end());
632}
633
634
635//=== Size and capacity.
636
637
638/**
639 * @fn size_type size() const
640 * @brief Returns the number of elements in the collection.
641 */
642template <class T, class BASE>
643inline
644typename DataVector<T, BASE>::size_type
645DataVector<T, BASE>::size() const noexcept
646{
647 return this->m_pCont.size();
648}
649
650
651/**
652 * @brief Resizes the collection to the specified number of elements.
653 * @param sz The new size of the collection.
654 *
655 * Note that this function differs from the standard in that it does
656 * not allow specifying the value of any inserted elements.
657 * They will always be 0.
658 *
659 * If the container is shrunk, elements will be deleted as with @c erase().
660 */
661template <class T, class BASE>
662void DataVector<T, BASE>::resize(size_type sz)
663{
664 if (sz < this->size()) {
665 this->erase (this->begin()+sz, this->end());
666 } else {
667 this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
668 SG::AuxVectorBase::resize<DataVector> (sz);
669 }
670}
671
672
673/**
674 * @brief Attempt to preallocate enough memory for a specified number
675 * of elements.
676 * @param n Number of elements required.
677 */
678template <class T, class BASE>
679inline
680void DataVector<T, BASE>::reserve (size_type n)
681{
682 this->m_pCont.reserve (n);
683 SG::AuxVectorBase::reserve<DataVector> (n);
684}
685
686
687//=== Element access.
688
689
690/**
691 * @brief Access an element, as an rvalue.
692 * @param n Array index to access.
693 * @return The element at @a n.
694 *
695 * No bounds checking is done.
696 * Note that we return a @c const @c T* rather than a reference.
697 */
698template <class T, class BASE>
699inline
700const T* DataVector<T, BASE>::operator[] (size_type n) const
701{
702 return do_cast(this->m_pCont[n]);
703}
704
705
706/**
707 * @brief Access an element, as an rvalue.
708 * @param n Array index to access.
709 * @return The element at @a n.
710 *
711 * This is a synonym for operator[] const, to be used when calling from root
712 * (where we can't readily call just the const version of a method).
713 */
714template <class T, class BASE>
715inline
716const T* DataVector<T, BASE>::get (size_type n) const
717{
718 return do_cast(this->m_pCont[n]);
719}
720
721
722/**
723 * @brief Access an element, as an lvalue.
724 * @param n Array index to access.
725 * @return Proxy to the element at @a n.
726 *
727 * No bounds checking is done.
728 * Note that we return a proxy object rather than a reference;
729 * the proxy will handle deleting an owned element if it's assigned to.
730 */
731template <class T, class BASE>
732inline
733typename DataVector<T, BASE>::ElementProxy
734DataVector<T, BASE>::operator[] (size_type n)
735{
736 return ElementProxy (this->m_pCont.begin() + n, this);
737}
738
739
740/**
741 * @brief Access an element, as an rvalue.
742 * @param n Array index to access.
743 * @return The element at @a n.
744 *
745 * Will raise @c std::out_of_range if the index is out-of-bounds.
746 * Note that we return a @c const @c T* rather than a reference.
747 */
748template <class T, class BASE>
749inline
750const T* DataVector<T, BASE>::at (size_type n) const
751{
752 return do_cast(this->m_pCont.at(n));
753}
754
755
756/**
757 * @brief Access an element, as an lvalue.
758 * @param n Array index to access.
759 * @return Proxy to the element at @a n.
760 *
761 * Will raise @c std::out_of_range if the index is out-of-bounds.
762 * Note that we return a proxy object rather than a reference;
763 * the proxy will handle deleting an owned element if it's assigned to.
764 */
765template <class T, class BASE>
766inline
767typename DataVector<T, BASE>::ElementProxy
768DataVector<T, BASE>::at (size_type n)
769{
770 // Can't use m_pCont's at here, because we need an iterator.
771 // So we have to do the bounds check ourselves.
772 if (n >= this->size())
773 CxxUtils::throw_out_of_range (__PRETTY_FUNCTION__, n, this->size(), this);
774 return ElementProxy (this->m_pCont.begin() + n, this);
775}
776
777
778/**
779 * @brief Access the first element in the collection as an rvalue.
780 * @return The first element in the collection.
781 *
782 * No checking is done to ensure that the container is not empty.
783 * Note that we return a @c const @c T* rather than a reference.
784 */
785template <class T, class BASE>
786inline
787const T* DataVector<T, BASE>::front() const
788{
789 return do_cast (this->m_pCont.front());
790}
791
792
793/**
794 * @brief Access the last element in the collection as an rvalue.
795 * @return The last element in the collection.
796 *
797 * No checking is done to ensure that the container is not empty.
798 * Note that we return a @c const @c T* rather than a reference.
799 */
800template <class T, class BASE>
801inline
802const T* DataVector<T, BASE>::back() const
803{
804 return do_cast (this->m_pCont.back());
805}
806
807
808/**
809 * @brief Access the first element in the collection as an lvalue.
810 * @return Proxy to the first element in the collection.
811 *
812 * No checking is done to ensure that the container is not empty.
813 * Note that we return a proxy object rather than a reference;
814 * the proxy will handle deleting an owned element if it's assigned to.
815 */
816template <class T, class BASE>
817inline
818typename DataVector<T, BASE>::ElementProxy
819DataVector<T, BASE>::front ()
820{
821 return ElementProxy (this->m_pCont.begin(), this);
822}
823
824
825/**
826 * @brief Access the last element in the collection as an lvalue.
827 * @return Proxy to the last element in the collection.
828 *
829 * No checking is done to ensure that the container is not empty.
830 * Note that we return a proxy object rather than a reference;
831 * the proxy will handle deleting an owned element if it's assigned to.
832 */
833template <class T, class BASE>
834inline
835typename DataVector<T, BASE>::ElementProxy
836DataVector<T, BASE>::back ()
837{
838 return ElementProxy (this->m_pCont.end()-1, this);
839}
840
841
842//=== Iterator creation.
843
844
845/**
846 * @brief Return a @c const_iterator pointing at the beginning
847 * of the collection.
848 * @return A @c const_iterator.
849 *
850 * Note that dereferencing the iterator will yield a @c const @c T* rather
851 * than a reference.
852 */
853template <class T, class BASE>
854inline
855typename DataVector<T, BASE>::const_iterator
856DataVector<T, BASE>::begin() const noexcept
857{
858 return const_iterator (this->m_pCont.begin());
859}
860
861
862/**
863 * @brief Return a @c const_iterator pointing past the end
864 * of the collection.
865 * @return A @c const_iterator.
866 *
867 * Note that dereferencing the iterator will yield a @c const @c T* rather
868 * than a reference.
869 */
870template <class T, class BASE>
871inline
872typename DataVector<T, BASE>::const_iterator
873DataVector<T, BASE>::end() const noexcept
874{
875 return const_iterator (this->m_pCont.end());
876}
877
878
879/**
880 * @brief Return an @c iterator pointing at the beginning
881 * of the collection.
882 * @return An @c iterator.
883 *
884 * Note that dereferencing the iterator will yield a proxy rather
885 * than a reference; the proxy will handle deleting an owned element
886 * if it's assigned to.
887 */
888template <class T, class BASE>
889inline
890typename DataVector<T, BASE>::iterator
891DataVector<T, BASE>::begin() noexcept
892{
893 return iterator (this->m_pCont.begin(), this);
894}
895
896
897/**
898 * @brief Return an @c iterator pointing past the end
899 * of the collection.
900 * @return An @c iterator.
901 *
902 * Note that dereferencing the iterator will yield a proxy rather
903 * than a reference; the proxy will handle deleting an owned element
904 * if it's assigned to.
905 */
906template <class T, class BASE>
907inline
908typename DataVector<T, BASE>::iterator
909DataVector<T, BASE>::end() noexcept
910{
911 return iterator (this->m_pCont.end(), this);
912}
913
914
915/**
916 * @brief Return a @c const_reverse_iterator pointing past the end
917 * of the collection.
918 * @return A @c const_reverse_iterator.
919 *
920 * Note that dereferencing the iterator will yield a @c const @c T* rather
921 * than a reference.
922 */
923template <class T, class BASE>
924inline
925typename DataVector<T, BASE>::const_reverse_iterator
926DataVector<T, BASE>::rbegin() const noexcept
927{
928 return const_reverse_iterator (end());
929}
930
931
932/**
933 * @brief Return a @c const_reverse_iterator pointing at the beginning
934 * of the collection.
935 * @return A @c const_reverse_iterator.
936 *
937 * Note that dereferencing the iterator will yield a @c const @c T* rather
938 * than a reference.
939 */
940template <class T, class BASE>
941inline
942typename DataVector<T, BASE>::const_reverse_iterator
943DataVector<T, BASE>::rend() const noexcept
944{
945 return const_reverse_iterator (begin());
946}
947
948
949/**
950 * @brief Return a @c reverse_iterator pointing past the end
951 * of the collection.
952 * @return A @c reverse_iterator.
953 *
954 * Note that dereferencing the iterator will yield a proxy rather
955 * than a reference; the proxy will handle deleting an owned element
956 * if it's assigned to.
957 */
958template <class T, class BASE>
959inline
960typename DataVector<T, BASE>::reverse_iterator
961DataVector<T, BASE>::rbegin() noexcept
962{
963 return reverse_iterator (iterator (this->m_pCont.end(), this));
964}
965
966
967/**
968 * @brief Return a @c reverse_iterator pointing at the beginning
969 * of the collection.
970 * @return A @c reverse_iterator.
971 *
972 * Note that dereferencing the iterator will yield a proxy rather
973 * than a reference; the proxy will handle deleting an owned element
974 * if it's assigned to.
975 */
976template <class T, class BASE>
977inline
978typename DataVector<T, BASE>::reverse_iterator
979DataVector<T, BASE>::rend() noexcept
980{
981 return reverse_iterator (iterator (this->m_pCont.begin(), this));
982}
983
984
985/**
986 * @brief Return a @c const_iterator pointing at the beginning
987 * of the collection.
988 * @return A @c const_iterator.
989 *
990 * Note that dereferencing the iterator will yield a @c const @c T* rather
991 * than a reference.
992 */
993template <class T, class BASE>
994inline
995typename DataVector<T, BASE>::const_iterator
996DataVector<T, BASE>::cbegin() const noexcept
997{
998 return const_iterator (this->m_pCont.begin());
999}
1000
1001
1002/**
1003 * @brief Return a @c const_iterator pointing past the end
1004 * of the collection.
1005 * @return A @c const_iterator.
1006 *
1007 * Note that dereferencing the iterator will yield a @c const @c T* rather
1008 * than a reference.
1009 */
1010template <class T, class BASE>
1011inline
1012typename DataVector<T, BASE>::const_iterator
1013DataVector<T, BASE>::cend() const noexcept
1014{
1015 return const_iterator (this->m_pCont.end());
1016}
1017
1018
1019/**
1020 * @brief Return a @c const_reverse_iterator pointing past the end
1021 * of the collection.
1022 * @return A @c const_reverse_iterator.
1023 *
1024 * Note that dereferencing the iterator will yield a @c const @c T* rather
1025 * than a reference.
1026 */
1027template <class T, class BASE>
1028inline
1029typename DataVector<T, BASE>::const_reverse_iterator
1030DataVector<T, BASE>::crbegin() const noexcept
1031{
1032 return const_reverse_iterator (cend());
1033}
1034
1035
1036/**
1037 * @brief Return a @c const_reverse_iterator pointing at the beginning
1038 * of the collection.
1039 * @return A @c const_reverse_iterator.
1040 *
1041 * Note that dereferencing the iterator will yield a @c const @c T* rather
1042 * than a reference.
1043 */
1044template <class T, class BASE>
1045inline
1046typename DataVector<T, BASE>::const_reverse_iterator
1047DataVector<T, BASE>::crend() const noexcept
1048{
1049 return const_reverse_iterator (cbegin());
1050}
1051
1052
1053//=== Insertion operations.
1054
1055
1056/**
1057 * @brief Add an element to the end of the collection.
1058 * @param pElem The element to add to the collection.
1059 *
1060 * The container's ownership policy will determine if it takes ownership
1061 * of the new element.
1062 *
1063 * Note: this method may only be called using the most derived
1064 * @c DataVector in the hierarchy.
1065 *
1066 * Returns the pushed pointer.
1067 */
1068template <class T, class BASE>
1069inline
1070typename DataVector<T, BASE>::value_type
1071DataVector<T, BASE>::push_back(value_type pElem)
1072{
1073 // Ensure we're not being called via a base class.
1074 testInsert ("push_back");
1075 this->m_pCont.push_back(static_cast<typename PtrVector::value_type>(pElem));
1076 SG::AuxVectorBase::resize<DataVector> (this->size());
1077 if (pElem && this->trackIndices())
1078 this->moveAuxNoClear (this->size()-1, pElem);
1079 return pElem;
1080}
1081
1082
1083/**
1084 * @brief Add an element to the end of the collection.
1085 * @param pElem The element to add to the collection.
1086 *
1087 * The container must be an owning container.
1088 *
1089 * Note: this method may only be called using the most derived
1090 * @c DataVector in the hierarchy.
1091 *
1092 * Returns the pushed pointer.
1093 */
1094template <class T, class BASE>
1095inline
1096typename DataVector<T, BASE>::value_type
1097DataVector<T, BASE>::push_back(std::unique_ptr<base_value_type> pElem)
1098{
1099 // Container must own its elements.
1100 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1101 SG::throwExcNonowningContainer();
1102
1103 // Ensure we're not being called via a base class.
1104 testInsert ("push_back");
1105 value_type ptr = pElem.release();
1106 this->m_pCont.push_back(ptr);
1107 SG::AuxVectorBase::resize<DataVector> (this->size());
1108 if (ptr && this->trackIndices())
1109 this->moveAuxNoClear (this->size()-1, ptr);
1110 return ptr;
1111}
1112
1113
1114/**
1115 * @brief Create and add a number of new elements to the end of the container.
1116 * @param n The number of new elements to add.
1117 * @param alloc Functional to call to allocate a new element to push.
1118 * Should be callable like <code>T* = alloc();</code>
1119 * For example:
1120 *@code
1121 * dv.push_new (n, [](){ return new Foo; });
1122 @endcode
1123 * It may also be useful to allocate from a @c DataPool.
1124 *
1125 * Note: this method may only be called using the most derived
1126 * @c DataVector in the hierarchy.
1127 *
1128 * Returns the original size of the vector.
1129 */
1130template <class T, class BASE>
1131template <CxxUtils::detail::AllocationFunction<T> F>
1132auto
1133DataVector<T, BASE>::push_new(size_type n, F alloc) -> size_type
1134{
1135 // Ensure we're not being called via a base class.
1136 testInsert ("push_new");
1137 bool trackIndices = this->trackIndices();
1138
1139 size_t sz = this->m_pCont.size();
1140 this->m_pCont.resize (sz + n);
1141 SG::AuxVectorBase::resize<DataVector> (this->size());
1142 for (size_t i = 0; i < n; i++) {
1143 T* p = alloc();
1144 if (!p) std::abort();
1145 this->m_pCont[sz+i] = p;
1146 if (trackIndices) {
1147 this->moveAuxNoClear (sz+i, p);
1148 }
1149 }
1150 return sz;
1151}
1152
1153
1154/**
1155 * @brief Add an element to the end of the collection.
1156 * @param pElem The element to add to the collection.
1157 *
1158 * The container's ownership policy will determine if it takes ownership
1159 * of the new element.
1160 *
1161 * Note: this method may only be called using the most derived
1162 * @c DataVector in the hierarchy.
1163 *
1164 * For @c DataVector, this is like the same as @c push_back, and
1165 * it returns the pushed element.
1166 * It's included just for interface compatibility with `std::vector`.
1167 */
1168template <class T, class BASE>
1169inline
1170typename DataVector<T, BASE>::value_type
1171DataVector<T, BASE>::emplace_back(value_type pElem)
1172{
1173 return this->push_back (pElem);
1174}
1175
1176
1177/**
1178 * @brief Add a new element to the collection.
1179 * @param position Iterator before which the element will be added.
1180 * @param pElem The element to add to the collection.
1181 * @return An iterator that points to the inserted data.
1182 *
1183 * The container's ownership policy will determine if it takes ownership
1184 * of the new element.
1185 *
1186 * Note: this method may only be called using the most derived
1187 * @c DataVector in the hierarchy.
1188 */
1189template <class T, class BASE>
1190typename DataVector<T, BASE>::iterator
1191DataVector<T, BASE>::insert(iterator position, value_type pElem)
1192{
1193 // Ensure we're not being called via a base class.
1194 testInsert ("insert");
1195 iterator ret (this->m_pCont.insert(position.base(), pElem), this);
1196 this->shift (ret - this->begin(), 1);
1197 this->moveAux (ret-this->begin(), pElem, false, true);
1198 return ret;
1199}
1200
1201
1202/**
1203 * @brief Add a new element to the collection.
1204 * @param position Iterator before which the element will be added.
1205 * @param pElem The element to add to the collection.
1206 * @return An iterator that points to the inserted data.
1207 *
1208 * The container must be an owning container.
1209 *
1210 * Note: this method may only be called using the most derived
1211 * @c DataVector in the hierarchy.
1212 */
1213template <class T, class BASE>
1214typename DataVector<T, BASE>::iterator
1215DataVector<T, BASE>::insert(iterator position,
1216 std::unique_ptr<base_value_type> pElem)
1217{
1218 // Container must own its elements.
1219 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1220 SG::throwExcNonowningContainer();
1221
1222 // Ensure we're not being called via a base class.
1223 testInsert ("insert");
1224 value_type ptr = pElem.release();
1225 iterator ret (this->m_pCont.insert(position.base(), ptr), this);
1226 this->shift (ret - this->begin(), 1);
1227 if (this->trackIndices())
1228 this->moveAuxNoClear (ret-this->begin(), ptr);
1229 return ret;
1230}
1231
1232
1233/**
1234 * @brief Add a new element to the collection.
1235 * @param position Iterator before which the element will be added.
1236 * @param pElem The element to add to the collection.
1237 * @return An iterator that points to the inserted data.
1238 *
1239 * The container's ownership policy will determine if it takes ownership
1240 * of the new element.
1241 *
1242 * Note: this method may only be called using the most derived
1243 * @c DataVector in the hierarchy.
1244 *
1245 * For @c DataVector, this is just the same as @c insert.
1246 * It's included just for interface compatibility with `std::vector`.
1247 */
1248template <class T, class BASE>
1249typename DataVector<T, BASE>::iterator
1250DataVector<T, BASE>::emplace(iterator position, value_type pElem)
1251{
1252 return this->insert (position, pElem);
1253}
1254
1255
1256/**
1257 * @brief Add a group of new elements to the collection.
1258 * @param position Iterator before which the element will be added.
1259 * @param first The start of the range to put in the container.
1260 * @param last The end of the range to put in the container.
1261 *
1262 * The container's ownership policy will determine if it takes ownership
1263 * of the new element.
1264 *
1265 * Note: this method may only be called using the most derived
1266 * @c DataVector in the hierarchy.
1267 *
1268 * This overload is for the case where the iterator value type
1269 * is convertible to T*.
1270 */
1271template <class T, class BASE>
1272template <class InputIterator,
1273 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
1274void DataVector<T, BASE>::insert(iterator position,
1275 InputIterator first,
1276 InputIterator last)
1277{
1278 // Make sure that the input iterator can actually be converted
1279 // to a T*. Lets us give a compilation error for this:
1280 // DATAVECTOR_BASE(D, B);
1281 // B* bb[] = ...
1282 // DataVector<D> d;
1283 // d.insert (d.begin(), bb, bb+1);
1284 // which would otherwise compile.
1285 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1286 static_assert (std::is_convertible_v<ittype, const T*>);
1287
1288 // Ensure we're not being called via a base class.
1289 testInsert ("insert");
1290 size_t idx = position - this->begin();
1291 size_t old_sz = this->m_pCont.size();
1292 this->m_pCont.insert(position.base(), first, last);
1293 size_t n = this->m_pCont.size() - old_sz;
1294 this->shift (idx, n);
1295 this->moveAux (idx, first, last, false, true);
1296}
1297
1298
1299/**
1300 * @brief Add a group of new elements to the collection.
1301 * @param position Iterator before which the element will be added.
1302 * @param first The start of the range to put in the container.
1303 * @param last The end of the range to put in the container.
1304 *
1305 * The container's ownership policy will determine if it takes ownership
1306 * of the new element.
1307 *
1308 * Note: this method may only be called using the most derived
1309 * @c DataVector in the hierarchy.
1310 *
1311 * This overload is for the case where the iterator value type
1312 * is convertible to unique_ptr<T>.
1313 */
1314template <class T, class BASE>
1315template <class InputIterator,
1316 DataVector_detail::enable_if_up_itr<InputIterator, T> >
1317void DataVector<T, BASE>::insert(iterator position,
1318 InputIterator first,
1319 InputIterator last)
1320{
1321 // Make sure that the input iterator can actually be converted
1322 // to a T*. Lets us give a compilation error for this:
1323 // DATAVECTOR_BASE(D, B);
1324 // B* bb[] = ...
1325 // DataVector<D> d;
1326 // d.insert (d.begin(), bb, bb+1);
1327 // which would otherwise compile.
1328 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1329 static_assert (std::is_convertible_v<typename ittype::pointer, const T*>);
1330
1331 // Ensure we're not being called via a base class.
1332 testInsert ("insert");
1333 size_t idx = position - this->begin();
1334 size_t old_sz = this->m_pCont.size();
1335 using CxxUtils::releasing_iterator;
1336 this->m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
1337 size_t n = this->m_pCont.size() - old_sz;
1338 this->shift (idx, n);
1339 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
1340}
1341
1342
1343/**
1344 * @brief Add a group of new elements to the collection.
1345 * @param position Iterator before which the element will be added.
1346 * @param l An initializer list.
1347 *
1348 * The container's ownership policy will determine if it takes ownership
1349 * of the new element.
1350 *
1351 * Note: this method may only be called using the most derived
1352 * @c DataVector in the hierarchy.
1353 */
1354template <class T, class BASE>
1355void DataVector<T, BASE>::insert(iterator position,
1356 std::initializer_list<value_type> l)
1357{
1358 insert (position, l.begin(), l.end());
1359}
1360
1361
1362/**
1363 * @brief Insert the contents of another @c DataVector,
1364 * with auxiliary data copied via move semantics.
1365 * @param position Iterator before which the new elements will be added.
1366 * @param other The vector to add.
1367 *
1368 * The ownership mode of this vector must be the same as @c other;
1369 * otherwise, an exception will be thrown.
1370 *
1371 * If both vectors are view vectors, then this is the same
1372 * as <code> insert (position, other.begin(), other.end()) </code>.
1373 *
1374 * Otherwise, the elements from @c other will be inserted into this vector.
1375 * This vector will take ownership of the elements, and the ownership
1376 * mode of @c other will be changed to @c VIEW_ELEMENTS.
1377 * Auxiliary data for these elements will be transferred,
1378 * using move semantics if possible. (Thus, the auxiliary store
1379 * for @c other may be modified and must not be locked.)
1380 * Finally, the auxiliary store pointer for @c other will be cleared
1381 * (but the store itself will not be deleted since it's not owned
1382 * by the vector).
1383 *
1384 * Note: this method may only be called using the most derived
1385 * @c DataVector in the hierarchy.
1386 */
1387template <class T, class BASE>
1388void
1389DataVector<T, BASE>::insertMove (iterator position, DataVector& other)
1390{
1391 if (this->m_ownPolicy != other.ownPolicy())
1392 throw SG::ExcInsertMoveOwnershipMismatch();
1393
1394 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
1395 this->insert (position, other.begin(), other.end());
1396 return;
1397 }
1398
1399 testInsert ("insertMove");
1400 size_t pos = position.base() - this->m_pCont.begin();
1401 this->m_pCont.insert (position.base(), other.begin(), other.end());
1402 this->setIndices (this->begin()+pos, this->end(), pos);
1403 other.m_ownPolicy = SG::VIEW_ELEMENTS;
1404
1405 SG::IAuxStore* otherStore = other.getStore();
1406 if (otherStore) {
1407 SG::IAuxStore* store = this->getStore();
1408 if (store) {
1409 if (!store->insertMove (pos, *otherStore))
1410 this->clearCache();
1411 }
1412 else if (this->hasStore())
1413 throw SG::ExcConstAuxData ("insertMove");
1414 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
1415 }
1416 else if (other.hasStore())
1417 throw SG::ExcConstAuxData ("insertMove");
1418}
1419
1420
1421//=== Erasure operations.
1422
1423
1424/**
1425 * @brief Remove element at a given position.
1426 * @param position Iterator pointing to the element to be removed.
1427 * @return An iterator pointing to the next element (or @c end()).
1428 *
1429 * If the container owns its elements, then the pointed-to element
1430 * will be deleted.
1431 */
1432template <class T, class BASE>
1433typename DataVector<T, BASE>::iterator
1434DataVector<T, BASE>::erase(iterator position)
1435{
1436 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1437 this->clearIndex (position);
1438 iterator ret (this->erase_base (position.base()), this);
1439 this->shift (ret - this->begin() + 1, -1);
1440 return ret;
1441}
1442
1443
1444/**
1445 * @brief Remove a range of elements.
1446 * @param first Iterator pointing to the first element to be removed.
1447 * @param last Iterator pointing one past the last element to be removed.
1448 * @return An iterator pointing to the element pointed to by @a last
1449 * prior to erasing (or @c end()).
1450 *
1451 * If the container owns its elements, then the removed elements
1452 * will be deleted. Any duplicates will be removed in this process,
1453 * but don't rely on this.
1454 */
1455template <class T, class BASE>
1456typename DataVector<T, BASE>::iterator
1457DataVector<T, BASE>::erase(iterator first, iterator last)
1458{
1459 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1460 this->clearIndices (first, last);
1461 iterator ret (this->erase_base (first.base(), last.base()), this);
1462 this->shift (ret - this->begin() + (last-first), -(last-first));
1463 return ret;
1464}
1465
1466
1467/**
1468 * @brief Remove the last element from the collection.
1469 *
1470 * If the container owns its elements, then the removed element
1471 * will be deleted.
1472 */
1473template <class T, class BASE>
1474void DataVector<T, BASE>::pop_back()
1475{
1476 if (!this->m_pCont.empty()) {
1477 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1478 this->doDelete (this->m_pCont.back());
1479 else
1480 this->clearIndex (iterator (this->m_pCont.end() - 1, this));
1481 this->m_pCont.pop_back();
1482 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
1483 }
1484}
1485
1486
1487/**
1488 * @brief Erase all the elements in the collection.
1489 *
1490 * If the container owns its elements, then the removed elements
1491 * will be deleted. Any duplicates will be removed in this process,
1492 * but don't rely on this.
1493 */
1494template <class T, class BASE>
1495inline
1496void DataVector<T, BASE>::clear()
1497{
1498 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1499 this->clearIndices (begin(), end());
1500 this->erase_base (this->m_pCont.begin(), this->m_pCont.end());
1501 SG::AuxVectorBase::resize<DataVector> (0);
1502}
1503
1504
1505//=== Swap and sort.
1506
1507
1508/**
1509 * @brief Swap this collection with another.
1510 * @param rhs The collection with which to swap.
1511 *
1512 * Ownership is swapped along with the collection content.
1513 *
1514 * Note: this method may only be called using the most-derived
1515 * @c DataVector in the hierarchy. The @a rhs must also be
1516 * referenced using the most-derived @c DataVector.
1517 *
1518 * Warning: If this container has auxiliary data, then this
1519 * is an O(N) operation, not O(1).
1520 */
1521template <class T, class BASE>
1522void DataVector<T, BASE>::swap(DataVector& rhs)
1523{
1524 testInsert ("swap");
1525 rhs.testInsert ("swap");
1526 std::swap(this->m_ownPolicy, rhs.m_ownPolicy);
1527 SG::AuxVectorBase::swap (rhs);
1528 this->m_pCont.swap(rhs.m_pCont);
1529 std::swap (this->m_deleter, rhs.m_deleter);
1530 this->setIndices (this->begin(), this->end());
1531 rhs.setIndices (rhs.begin(), rhs.end());
1532}
1533
1534
1535/**
1536 * @brief Swap the referents of two @c DataVector iterators.
1537 * @param a The first iterator for the swap.
1538 * @param b The second iterator for the swap.
1539 */
1540template <class T, class BASE>
1541void DataVector<T, BASE>::iter_swap (iterator a, iterator b)
1542{
1543 if (a.ownPolicy() != b.ownPolicy()) {
1544 throw SG::ExcBadIterSwap();
1545 }
1546 a.testInsert ("iter_swap");
1547 b.testInsert ("iter_swap");
1548 std::iter_swap (a.base(), b.base());
1549 DataVector* acont = a.container();
1550 DataVector* bcont = b.container();
1551 if (typename SG::AuxStore_traits<DataVector>::flag())
1552 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
1553 b.base() - bcont->stdcont().begin(),
1554 DataModel_detail::DVLCast<DataVector>::cast(*a.base()),
1555 DataModel_detail::DVLCast<DataVector>::cast(*b.base()),
1556 bcont);
1557}
1558
1559
1560/**
1561 * @brief Sort the container.
1562 *
1563 * This just sorts by pointer value, so it's probably not very useful.
1564 */
1565template <class T, class BASE>
1566void DataVector<T, BASE>::sort()
1567{
1568 typedef std::less<typename PtrVector::value_type> less;
1569 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1570 DataModel_detail::Compwrapper<DataVector, less> (less()));
1571 this->resortAux (this->begin(), this->end());
1572}
1573
1574
1575/**
1576 * @brief Sort the container with a user-specified comparison operator.
1577 * @param comp Functional to compare two values.
1578 */
1579template <class T, class BASE>
1580template <class COMPARE>
1581void DataVector<T, BASE>::sort(COMPARE comp)
1582{
1583 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1584 DataModel_detail::Compwrapper<DataVector, COMPARE> (comp));
1585 this->resortAux (this->begin(), this->end());
1586}
1587
1588
1589//=== Non-standard operations.
1590
1591
1592/**
1593 * @brief Swap one element out of the container.
1594 * @param index Index of the element in the container to swap.
1595 * @param newElement New element to put in the container.
1596 * May be 0.
1597 * @param oldElem Reference to receive the element removed from the
1598 * container.
1599 *
1600 * Reference @a oldElem is initialized with element @a index of the
1601 * collection (no bounds checking). Then element @a index is set
1602 * to @newElem. If the collection owns its elements, then it will
1603 * take ownership of @a newElem and release (without deleting)
1604 * the element returned through @a oldElem.
1605 *
1606 * Note: this method may only be called using the most derived
1607 * @c DataVector in the hierarchy.
1608 */
1609template <class T, class BASE>
1610void DataVector<T, BASE>::swapElement(size_type index,
1611 value_type newElem,
1612 reference oldElem)
1613{
1614 testInsert ("swapElement");
1615 oldElem =
1616 DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]);
1617 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1618 this->m_pCont[index] = newElem;
1619 this->moveAux (index, newElem);
1620}
1621
1622
1623/**
1624 * @brief Swap one element out of the container.
1625 * @param pos The element in the container to swap.
1626 * @param newElem New element to put in the container.
1627 * May be 0.
1628 * @param oldElem Reference to receive the element removed from the
1629 * container.
1630 *
1631 * Reference @a oldElem is initialized with element @a pos of the
1632 * collection (no bounds checking). Then element @a index is set
1633 * to @c newElem. If the collection owns its elements, then it will
1634 * take ownership of @a newElem and release (without deleting)
1635 * the element returned through @a oldElem.
1636 *
1637 * Note: this method may only be called using the most derived
1638 * @c DataVector in the hierarchy.
1639 */
1640template <class T, class BASE>
1641void DataVector<T, BASE>::swapElement(iterator pos,
1642 value_type newElem,
1643 reference oldElem)
1644{
1645 testInsert ("swapElement");
1646 oldElem =
1647 DataModel_detail::DVLCast<DataVector>::cast(*pos.base());
1648 this->clearIndex (pos);
1649 *pos.base() = newElem;
1650 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
1651}
1652
1653
1654/**
1655 * @brief Swap one element out of the container.
1656 * @param index Index of the element in the container to swap.
1657 * @param newElement New element to put in the container.
1658 * May be 0.
1659 * @param oldElem Reference to receive the element removed from the
1660 * container.
1661 *
1662 * Reference @a oldElem is initialized with element @a index of the
1663 * collection (no bounds checking). Then element @a index is set
1664 * to @newElem.
1665 *
1666 * The collection must own its elements to use its interface.
1667 * The collection will take ownership of @c newElem and will return
1668 * ownership of @c oldElem.
1669 *
1670 * Note: this method may only be called using the most derived
1671 * @c DataVector in the hierarchy.
1672 */
1673template <class T, class BASE>
1674void DataVector<T, BASE>::swapElement(size_type index,
1675 std::unique_ptr<base_value_type> newElem,
1676 std::unique_ptr<base_value_type>& oldElem)
1677{
1678 // Container must own its elements.
1679 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1680 SG::throwExcNonowningContainer();
1681
1682 testInsert ("swapElement");
1683 oldElem = std::unique_ptr<base_value_type>
1684 (DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]));
1685 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1686 value_type ptr = newElem.release();
1687 this->m_pCont[index] = ptr;
1688 this->moveAux (index, ptr);
1689}
1690
1691
1692/**
1693 * @brief Swap one element out of the container.
1694 * @param pos The element in the container to swap.
1695 * @param newElem New element to put in the container.
1696 * May be 0.
1697 * @param oldElem Reference to receive the element removed from the
1698 * container.
1699 *
1700 * Reference @a oldElem is initialized with element @a pos of the
1701 * collection (no bounds checking). Then element @a index is set
1702 * to @c newElem.
1703 *
1704 * The collection must own its elements to use its interface.
1705 * The collection will take ownership of @c newElem and will return
1706 * ownership of @c oldElem.
1707 *
1708 * Note: this method may only be called using the most derived
1709 * @c DataVector in the hierarchy.
1710 */
1711template <class T, class BASE>
1712void DataVector<T, BASE>::swapElement(iterator pos,
1713 std::unique_ptr<base_value_type> newElem,
1714 std::unique_ptr<base_value_type>& oldElem)
1715{
1716 // Container must own its elements.
1717 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1718 SG::throwExcNonowningContainer();
1719
1720 testInsert ("swapElement");
1721 oldElem = std::unique_ptr<base_value_type>
1722 (DataModel_detail::DVLCast<DataVector>::cast(*pos.base()));
1723 this->clearIndex (pos);
1724 value_type ptr = newElem.release();
1725 *pos.base() = ptr;
1726 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
1727}
1728
1729
1730/**
1731 * @brief Erase all the elements in the collection, and reset
1732 * the ownership mode.
1733 * @param ownPolicy The new ownership policy of the container.
1734 *
1735 * If the container owns its elements, then the removed elements
1736 * will be deleted. Any duplicates will be removed in this process,
1737 * but don't rely on this.
1738 */
1739template <class T, class BASE>
1740void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy)
1741{
1742 this->clear();
1743 this->m_ownPolicy = ownPolicy;
1744 this->template initAuxVectorBase<DataVector> (ownPolicy,
1745 SG::DEFAULT_TRACK_INDICES);
1746}
1747
1748
1749/**
1750 * @brief Erase all the elements in the collection, and reset
1751 * the ownership mode.
1752 * @param ownPolicy The new ownership policy of the container.
1753 * @param trackIndices The index tracking policy.
1754 *
1755 * If the container owns its elements, then the removed elements
1756 * will be deleted. Any duplicates will be removed in this process,
1757 * but don't rely on this.
1758 */
1759template <class T, class BASE>
1760void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy,
1761 SG::IndexTrackingPolicy trackIndices)
1762{
1763 this->clear();
1764 this->m_ownPolicy = ownPolicy;
1765 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
1766}
1767
1768
1769/**
1770 * @brief Return the DV/DL info struct for this class.
1771 *
1772 * This can be used to make sure that it's instantiated.
1773 */
1774template <class T, class BASE>
1775const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo()
1776{
1777 static const DataModel_detail::DVLInfo<DataVector<T, BASE> > info;
1778 return info;
1779}
1780
1781
1782/**
1783 * @brief Erase all the elements in the collection, and change
1784 * how elements are to be deleted.
1785 * @param deleter Object to be used to delete object.
1786 * Passing nullptr will change back to the default.
1787 *
1788 * If the container owns its elements, then the removed elements
1789 * will be deleted. Any duplicates will be removed in this process,
1790 * but don't rely on this.
1791 * After the current elements are deleted, the Deleter object is changed.
1792 */
1793template <class T, class BASE>
1794void DataVector<T, BASE>::clear (std::unique_ptr<Deleter> deleter)
1795{
1796 this->clear();
1797 delete this->m_deleter;
1798 this->m_deleter = deleter.release();
1799}
1800
1801
1802/**
1803 * @brief Return the DV/DL info struct for this class.
1804 *
1805 * This can be used to make sure that it's instantiated.
1806 */
1807template <class T, class BASE>
1808const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo_v() const
1809{
1810 return DataVector<T, BASE>::dvlinfo();
1811}
1812
1813
1814/**
1815 * @brief Return the offset of a base @c DataVector class.
1816 * @param ti @c std::type_info of the desired class.
1817 *
1818 * If @c ti represents a @c DataVector base class of this one,
1819 * then return the offset of that base class. Otherwise, return -1.
1820 *
1821 * This function is here due to limitations of root 6, which can't
1822 * calculate these offsets correctly from the dictionary if
1823 * virtual derivation is used.
1824 */
1825template <class T, class BASE>
1826int DataVector<T, BASE>::baseOffset (const std::type_info& ti)
1827{
1828 DataVector dv;
1829 return baseOffset1 (reinterpret_cast<const char*>(&dv), dv, ti);
1830}
1831
1832
1833/**
1834 * @brief Convert to @c AuxVectorBase.
1835 *
1836 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
1837 * Present in @c DataVector as well for consistency.
1838 * We only really need it in the base class; however, root6 fails
1839 * constructing a @c TMethodCall for this if there is virtual
1840 * derivation. A workaround is to redeclare this in the derived
1841 * classes too.
1842 */
1843template <class T, class BASE>
1844const SG::AuxVectorBase& DataVector<T, BASE>::auxbase() const
1845{
1846 return *this;
1847}
1848
1849
1850//=== Internal operations.
1851
1852
1853/**
1854 * @brief Helper for @c baseOffset.
1855 * @param p Pointer to the start of the top-level object.
1856 * @param dv Reference to the DataVector object.
1857 * @param ti @c std::type_info of the desired class.
1858 *
1859 * If @c ti represents a @c DataVector base class of this one,
1860 * then return the offset of that base class. Otherwise, return -1.
1861 *
1862 */
1863template <class T, class BASE>
1864int DataVector<T, BASE>::baseOffset1 (const char* p, const DataVector& dv,
1865 const std::type_info& ti)
1866{
1867 if (typeid(DataVector) == ti)
1868 return reinterpret_cast<const char*>(&dv) - p;
1869 return BASE::baseOffset1 (p, dv, ti);
1870}
1871
1872
1873/**
1874 * @brief Reset indices / reorder aux data after elements have been permuted.
1875 * @param beg Start of the range of elements to process.
1876 * @param end End of the range of elements to process.
1877 *
1878 * Call this after some operation that has permuted the elements in the
1879 * container (such as sort). The index information in the elements
1880 * will be used to permute all auxiliary data in the same way.
1881 * Finally, all the indices will be reset in the correct order.
1882 */
1883template <class T, class BASE>
1884void DataVector<T, BASE>::resortAux (iterator beg, iterator end)
1885{
1886 if (typename SG::AuxStore_traits<DataVector>::flag() &&
1887 beg >= this->begin() && end <= this->end())
1888 {
1889 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
1890 }
1891}
1892
1893
1894/**
1895 * @brief Test if we can insert; raise an exception if not.
1896 * @param op Description of the attempted operation.
1897 *
1898 * In order to maintain type-safety, we can only allow insertions
1899 * using the most-derived instance of @c DataVector. This checks
1900 * this by testing the @c m_isMostDerived, which is set by the constructors
1901 * to true only for the most-derived instance.
1902 * If the test fails, we call to potentially out-of-line code to continue.
1903 */
1904template <class T, class BASE>
1905inline
1906void DataVector<T, BASE>::testInsert (const char* op)
1907{
1908 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
1909 return;
1910 this->testInsertOol (op);
1911}
1912
1913
1914/**
1915 * @brief Test if we can insert; raise an exception if not.
1916 * @param op Description of the attempted operation.
1917 *
1918 * This continues the test of @c testInsert. There is one case
1919 * where @c m_isMostDerived may not be set correctly. If this container
1920 * was made via copy construction, then all the @c m_isMostDerived flags
1921 * will be false. So we call @c setMostDerived to set the flags correctly
1922 * and test again. If the test fails again, then we raise an exception.
1923 */
1924template <class T, class BASE>
1925void DataVector<T, BASE>::testInsertOol (const char* op)
1926{
1927 this->setMostDerived();
1928 if (!m_isMostDerived)
1929 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
1930}
1931
1932
1933/**
1934 * @brief Handle element assignment.
1935 * @param pos Position in the container to assign.
1936 * @param newElem The new element to assign.
1937 *
1938 * The old element is freed if this container owns elements.
1939 * Auxiliary data are copied if appropriate.
1940 */
1941template <class T, class BASE>
1942void DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1943 value_type newElem)
1944{
1945 testInsert ("assignElement");
1946 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1947 this->doDelete (*pos);
1948 else
1949 this->clearIndex (iterator (pos, this));
1950 *pos = newElem;
1951 this->moveAux (pos - this->m_pCont.begin(), newElem);
1952}
1953
1954
1955/**
1956 * @brief Handle element assignment.
1957 * @param pos Position in the container to assign.
1958 * @param newElem The new element to assign.
1959 *
1960 * The container must own its elements.
1961 * Auxiliary data are copied if appropriate.
1962 */
1963template <class T, class BASE>
1964void
1965DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1966 std::unique_ptr<base_value_type> newElem)
1967{
1968 // Container must own its elements.
1969 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1970 SG::throwExcNonowningContainer();
1971
1972 testInsert ("assignElement");
1973 this->doDelete (*pos);
1974 value_type ptr = newElem.release();
1975 *pos = ptr;
1976 this->moveAux (pos - this->m_pCont.begin(), ptr);
1977}
1978
1979
1980/**
1981 * @brief Handle element assignment from a base pointer.
1982 * @param pos Position in the container to assign.
1983 * @param newElem The new element to assign.
1984 *
1985 * The old element is freed if this container owns elements.
1986 * Auxiliary data are copied if appropriate.
1987 */
1988template <class T, class BASE>
1989void
1990DataVector<T, BASE>::assignBaseElement (typename BaseContainer::iterator pos,
1991 typename BaseContainer::value_type newElem)
1992{
1993 testInsert ("assignBaseElement");
1994 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1995 this->doDelete (*pos);
1996 else
1997 this->clearIndex (iterator (pos, this));
1998 *pos = newElem;
1999 if (typename SG::AuxStore_traits<DataVector>::flag())
2000 this->moveAux (pos - this->m_pCont.begin(),
2001 DataModel_detail::DVLCast<DataVector>::cast(newElem));
2002}
2003
2004
2005/**
2006 * @brief Shift the auxiliary elements of the container.
2007 * @param pos The starting index for the shift.
2008 * @param offs The (signed) amount of the shift.
2009 *
2010 * The elements in the container should have already been shifted;
2011 * this operation will then adjust the element indices and also shift
2012 * the elements in the vectors for all aux data items.
2013 * @c offs may be either positive or negative.
2014 *
2015 * If @c offs is positive, then the container is growing.
2016 * The container size should be increased by @c offs,
2017 * the element at @c pos moved to @c pos + @c offs,
2018 * and similarly for following elements.
2019 * The elements between @c pos and @c pos + @c offs should
2020 * be default-initialized.
2021 *
2022 * If @c offs is negative, then the container is shrinking.
2023 * The element at @c pos should be moved to @c pos + @c offs,
2024 * and similarly for following elements.
2025 * The container should then be shrunk by @c -offs elements
2026 * (running destructors as appropriate).
2027 */
2028template <class T, class BASE>
2029void DataVector<T, BASE>::shift (size_t pos, ptrdiff_t offs)
2030{
2031 SG::AuxVectorBase::shift (*this, pos, offs);
2032}
2033
2034
2035/**
2036 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
2037 * @param p The value to convert.
2038 * @return The value as a @c const @c T*.
2039 *
2040 * The conversion will be done with @c static_cast if possible,
2041 * with @c dynamic_cast otherwise.
2042 */
2043template <class T, class BASE>
2044inline
2045const T*
2046DataVector<T, BASE>::do_cast (const typename PtrVector::value_type p)
2047{
2048 return DataModel_detail::DVLCast<DataVector>::cast (p);
2049}
2050
2051
2052/**
2053 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
2054 * @param p The value to convert.
2055 * @return The value as a @c T*.
2056 *
2057 * The conversion will be done with @c static_cast if possible,
2058 * with @c dynamic_cast otherwise.
2059 */
2060template <class T, class BASE>
2061inline
2062T*
2063DataVector<T, BASE>::do_cast_nc (typename PtrVector::value_type p)
2064{
2065 return DataModel_detail::DVLCast<DataVector>::cast (p);
2066}
2067
2068
2069/**
2070 * @brief Find the most-derived @c DataVector class in the hierarchy.
2071 * @return The @c type_info for the class for which this method gets run.
2072 *
2073 * This is used to generate a nice error message when the most-derived
2074 * check for insertions fails.
2075 * Every @c DataVector defines this virtual method, so when it's
2076 * called, the one corresponding to the most-derived @c DataVector
2077 * gets run.
2078 */
2079template <class T, class BASE>
2080const std::type_info& DataVector<T, BASE>::dv_typeid() const
2081{
2082 return typeid(DataVector);
2083}
2084
2085
2086/**
2087 * @brief Clear @c m_isMostDerived for this instance and for all bases.
2088 *
2089 * Called from the constructor after setting @c m_isMostDerived.
2090 */
2091template <class T, class BASE>
2092inline
2093void DataVector<T, BASE>::clearMostDerived()
2094{
2095 this->m_isMostDerived = false;
2096 BASE::clearMostDerived();
2097}
2098
2099
2100/**
2101 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
2102 *
2103 * Called from @c testInsert if the test fails. The flag may not have
2104 * been set if this container was made via copy construction, so set
2105 * it appropriately now so we can test again.
2106 */
2107template <class T, class BASE>
2108void DataVector<T, BASE>::setMostDerived()
2109{
2110 m_isMostDerived = true;
2111 BASE::clearMostDerived();
2112}
2113
2114
2115//****************************************************************************
2116// Specialized (base) DataVector implementation.
2117//
2118
2119
2120// An abbreviation for the DataVector specialization to try to make
2121// things a little more readable.
2122#define DATAVECTOR DataVector<T, DataModel_detail::NoBase>
2123
2124
2125//=== Constructors, destructors, assignment.
2126
2127/**
2128 * @brief Default constructor.
2129 * @param ownPolicy The ownership mode for the container.
2130 * @param trackIndices The index tracking policy.
2131 *
2132 * By default, a @c DataVector will own its elements.
2133 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2134 */
2135template <class T>
2136inline
2137DATAVECTOR::DataVector
2138 (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2139 SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
2140 : m_ownPolicy(ownPolicy)
2141{
2142 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2143 this->m_isMostDerived = true;
2144}
2145
2146
2147/**
2148 * @brief Sized constructor.
2149 * @param n The size of the container.
2150 * @param ownPolicy The ownership mode for the container.
2151 * @param trackIndices The index tracking policy.
2152 *
2153 * Note that unlike the standard vector constructor, you can't specify
2154 * an initial value here. The container will be initialized with 0's.
2155 *
2156 * By default, a @c DataVector will own its elements.
2157 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2158 */
2159template <class T>
2160inline
2161DATAVECTOR::DataVector
2162 (size_type n,
2163 SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2164 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
2165 : m_ownPolicy(ownPolicy),
2166 m_pCont (n)
2167{
2168 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2169 this->m_isMostDerived = true;
2170}
2171
2172
2173/**
2174 * @brief Copy constructor.
2175 * @param rhs The container from which to copy.
2176 *
2177 * This is a `shallow' copy; the new container will not own its elements.
2178 */
2179template <class T>
2180inline
2181DATAVECTOR::DataVector(const DataVector& rhs)
2182 : AuxVectorBase(),
2183 m_ownPolicy(SG::VIEW_ELEMENTS),
2184 m_pCont(rhs.m_pCont)
2185{
2186 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2187 SG::DEFAULT_TRACK_INDICES);
2188 // Leave m_isMostDerived false here, because we may be being called
2189 // from a derived class implicit copy constructor. The flags will get
2190 // set correctly when @c testInsert gets called.
2191}
2192
2193
2194/**
2195 * @brief Move constructor.
2196 * @param rhs The container from which to move.
2197 *
2198 * Any auxiliary data will be moved along with the container contents.
2199 */
2200template <class T>
2201inline
2202DATAVECTOR::DataVector(DataVector&& rhs) noexcept
2203 : AuxVectorBase (std::move (rhs)),
2204 m_ownPolicy(rhs.m_ownPolicy),
2205 m_pCont(std::move (rhs.m_pCont))
2206{
2207 m_deleter = std::move(rhs.m_deleter);
2208 rhs.m_deleter = nullptr;
2209
2210 // Need to reset the container pointer on elements.
2211 // Functions called from here can throw GaudiException.
2212 // However, logically that should not actually happen; so leave this
2213 // declared as noexcept.
2214 this->setIndices (this->begin(), this->end());
2215
2216 // This doesn't get called from derived classes.
2217 // Go ahead and set this flag now.
2218 m_isMostDerived = true;
2219}
2220
2221
2222/**
2223 * @brief Constructor from iterators.
2224 * @param first The start of the range to put in the new container.
2225 * @param last The end of the range to put in the new container.
2226 * @param ownPolicy The ownership mode for the container.
2227 * @param trackIndices The index tracking policy.
2228 * @param store An associated auxiliary data store.
2229 *
2230 * By default, a view container is made, which does not own its elements.
2231 * To have the container take ownership of the pointers passed
2232 * to this constructor, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2233 */
2234template <class T>
2235template <class InputIterator>
2236inline
2237DATAVECTOR::DataVector
2238 (InputIterator first,
2239 InputIterator last,
2240 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2241 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2242 SG::IAuxStore* store /*= 0*/)
2243 : m_ownPolicy(ownPolicy)
2244{
2245 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2246 this->m_isMostDerived = true;
2247 if (store)
2248 this->setStore (store);
2249 insert (this->begin(), first, last);
2250}
2251
2252
2253/**
2254 * @brief Constructor from an initializer list.
2255 * @param l An initializer list.
2256 * @param last The end of the range to put in the new container.
2257 * @param ownPolicy The ownership mode for the container.
2258 * @param trackIndices The index tracking policy.
2259 * @param store An associated auxiliary data store.
2260 *
2261 *
2262 * A @c DataVector constructed this way will *not* own its elements
2263 * by default. To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2264 */
2265template <class T>
2266inline
2267DATAVECTOR::DataVector
2268 (std::initializer_list<value_type> l,
2269 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2270 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2271 SG::IAuxStore* store /*= 0*/)
2272 : DataVector (l.begin(), l.end(), ownPolicy, trackIndices, store)
2273{
2274}
2275
2276
2277/**
2278 * @brief Assignment operator.
2279 * @param rhs The DataVector from which to assign.
2280 * @return This object.
2281 *
2282 * This is a `shallow' copy; after the completion of this, the @c DataVector
2283 * will not own its elements. Any elements it owned prior to this call
2284 * will be released.
2285 *
2286 * Note: this method may only be called using the most derived
2287 * @c DataVector in the hierarchy.
2288 */
2289template <class T>
2290inline
2291DATAVECTOR& DATAVECTOR::operator= (const DataVector& rhs)
2292{
2293 if (&rhs != this) {
2294 // Ensure we're not being called via a base class.
2295 // This can throw an exception, so this method should not be noexcept.
2296 testInsert ("assignment operator");
2297 clear(); // Release any currently-owned elements.
2298 m_ownPolicy = SG::VIEW_ELEMENTS;
2299 this->setStore ((SG::IConstAuxStore*)0);
2300 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2301 SG::DEFAULT_TRACK_INDICES);
2302 m_pCont = rhs.m_pCont;
2303 }
2304 return *this;
2305}
2306
2307
2308/**
2309 * @brief Move assignment.
2310 * @param rhs The container from which to move.
2311 *
2312 * Any auxiliary data will be moved along with the container contents.
2313 */
2314template <class T>
2315DATAVECTOR& DATAVECTOR::operator= (DATAVECTOR&& rhs)
2316{
2317 if (this != &rhs) {
2318 // Ensure we're not being called via a base class.
2319 // This can throw an exception, so this method should not be noexcept.
2320 testInsert ("assignment operator");
2321
2322 this->clear(); // Release any currently-owned elements.
2323
2324 SG::AuxVectorBase::operator= (std::move (rhs));
2325 this->m_ownPolicy = rhs.m_ownPolicy;
2326 this->m_pCont = std::move (rhs.m_pCont);
2327
2328 delete this->m_deleter;
2329 this->m_deleter = std::move(rhs.m_deleter);
2330 rhs.m_deleter = nullptr;
2331
2332 // Need to reset the container pointer on elements.
2333 this->setIndices (this->begin(), this->end());
2334 }
2335 return *this;
2336}
2337
2338
2339/**
2340 * @brief Assignment operator, from an initializer list.
2341 * @param l An initializer list.
2342 * @return This object.
2343 *
2344 * This is equivalent to @c assign.
2345 * Any existing owned elements will be released.
2346 * The @c DataVector's ownership policy determines whether it will take
2347 * ownership of the new elements.
2348 */
2349template <class T>
2350inline
2351DATAVECTOR& DATAVECTOR::operator= (std::initializer_list<value_type> l)
2352{
2353 this->assign (l.begin(), l.end());
2354 return *this;
2355}
2356
2357
2358/**
2359 * @brief Assign from iterators.
2360 * @param first The start of the range to put in the container.
2361 * @param last The end of the range to put in the container.
2362 *
2363 * Any existing owned elements will be released.
2364 * The @c DataVector's ownership policy determines whether it will take
2365 * ownership of the new elements.
2366 */
2367template <class T>
2368template <class InputIterator>
2369void DATAVECTOR::assign (InputIterator first,
2370 InputIterator last)
2371{
2372 // Ensure we're not being called via a base class.
2373 testInsert ("assign");
2374 clear(); // Release any currently-owned elements.
2375 insert(begin(), first, last);
2376}
2377
2378
2379/**
2380 * @brief Assign from an initializer list.
2381 * @param l An initializer list.
2382 *
2383 * Any existing owned elements will be released.
2384 * The @c DataVector's ownership policy determines whether it will take
2385 * ownership of the new elements.
2386 */
2387template <class T>
2388void DATAVECTOR::assign (std::initializer_list<value_type> l)
2389{
2390 this->assign (l.begin(), l.end());
2391}
2392
2393
2394/**
2395 * @brief Destructor.
2396 *
2397 * If this container owns its elements, the contained elements will
2398 * be deleted as well. Before doing this, the destructor will scan
2399 * for duplicate pointers (takes @f$n \log n@f$ time); duplicates are only
2400 * destroyed once. Duplicates should, however, be considered an error;
2401 * don't rely on this behavior.
2402 */
2403template <class T>
2404DATAVECTOR::~DataVector()
2405{
2406 if (m_ownPolicy == SG::OWN_ELEMENTS) {
2407 typename PtrVector::iterator new_end =
2408 DataVector_detail::remove_duplicates(m_pCont.begin(), m_pCont.end());
2409 this->doDelete (m_pCont.begin(), new_end);
2410 }
2411 delete m_deleter;
2412}
2413
2414
2415//=== Size and capacity.
2416
2417
2418/**
2419 * @brief Returns the number of elements in the collection.
2420 */
2421template <class T>
2422inline
2423typename DATAVECTOR::size_type DATAVECTOR::size() const noexcept
2424{
2425 return m_pCont.size();
2426}
2427
2428
2429/**
2430 * @brief Returns the number of elements in the collection.
2431 *
2432 * This version is virtual, to be callable from the AuxData
2433 * base class.
2434 */
2435template <class T>
2436inline
2437typename DATAVECTOR::size_type DATAVECTOR::size_v() const
2438{
2439 return this->size();
2440}
2441
2442
2443/**
2444 * @brief Returns the @c size() of the largest possible collection.
2445 */
2446template <class T>
2447inline
2448typename DATAVECTOR::size_type DATAVECTOR::max_size() const noexcept
2449{
2450 return m_pCont.max_size();
2451}
2452
2453
2454/**
2455 * @brief Resizes the collection to the specified number of elements.
2456 * @param sz The new size of the collection.
2457 *
2458 * Note that this function differs from the standard in that it does
2459 * not allow specifying the value of any inserted elements.
2460 * They will always be 0.
2461 *
2462 * If the container is shrunk, elements will be deleted as with @c erase().
2463 */
2464template <class T>
2465void DATAVECTOR::resize(size_type sz)
2466{
2467 if (sz < this->size()) {
2468 this->erase (this->begin()+sz, this->end());
2469 } else {
2470 this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
2471 SG::AuxVectorBase::resize<DataVector> (sz);
2472 }
2473}
2474
2475
2476/**
2477 * @brief Returns the total number of elements that the collection can hold
2478 * before needing to allocate more memory.
2479 */
2480template <class T>
2481inline
2482typename DATAVECTOR::size_type DATAVECTOR::capacity() const noexcept
2483{
2484 return m_pCont.capacity();
2485}
2486
2487
2488/**
2489 * @brief Returns the total number of elements that the collection can hold
2490 * before needing to allocate more memory.
2491 *
2492 * This version is virtual, to be callable from the AuxData
2493 * base class.
2494 */
2495template <class T>
2496inline
2497typename DATAVECTOR::size_type DATAVECTOR::capacity_v() const
2498{
2499 return capacity();
2500}
2501
2502
2503/**
2504 * @brief Returns @c true if the collection is empty.
2505 */
2506template <class T>
2507inline
2508bool DATAVECTOR::empty() const noexcept
2509{
2510 return m_pCont.empty();
2511}
2512
2513
2514/**
2515 * @brief Attempt to preallocate enough memory for a specified number
2516 * of elements.
2517 * @param n Number of elements required.
2518 */
2519template <class T>
2520inline
2521void DATAVECTOR::reserve (size_type n)
2522{
2523 m_pCont.reserve (n);
2524 SG::AuxVectorBase::reserve<DataVector> (n);
2525}
2526
2527
2528/**
2529 * @brief Change the vector capacity to match the current size.
2530 *
2531 * Note: this does not affect auxiliary data.
2532 */
2533template <class T>
2534inline
2535void DATAVECTOR::shrink_to_fit()
2536{
2537 m_pCont.shrink_to_fit();
2538}
2539
2540
2541//=== Element access.
2542
2543
2544/**
2545 * @brief Access an element, as an rvalue.
2546 * @param n Array index to access.
2547 * @return The element at @a n.
2548 *
2549 * No bounds checking is done.
2550 * Note that we return a @c const @c T* rather than a reference.
2551 */
2552template <class T>
2553inline
2554const T* DATAVECTOR::operator[] (size_type n) const
2555{
2556 return m_pCont[n];
2557}
2558
2559
2560/**
2561 * @brief Access an element, as an rvalue.
2562 * @param n Array index to access.
2563 * @return The element at @a n.
2564 *
2565 * This is a synonym for operator[] const, to be used when calling from root
2566 * (where we can't readily call just the const version of a method).
2567 */
2568template <class T>
2569inline
2570const T* DATAVECTOR::get (size_type n) const
2571{
2572 return do_cast(this->m_pCont[n]);
2573}
2574
2575
2576/**
2577 * @brief Access an element, as an lvalue.
2578 * @param n Array index to access.
2579 * @return Proxy to the element at @a n.
2580 *
2581 * No bounds checking is done.
2582 * Note that we return a proxy object rather than a reference;
2583 * the proxy will handle deleting an owned element if it's assigned to.
2584 */
2585template <class T>
2586inline
2587typename DATAVECTOR::ElementProxy DATAVECTOR::operator[] (size_type n)
2588{
2589 return ElementProxy (m_pCont.begin() + n, this);
2590}
2591
2592
2593/**
2594 * @brief Access an element, as an rvalue.
2595 * @param n Array index to access.
2596 * @return The element at @a n.
2597 *
2598 * Will raise @c std::out_of_range if the index is out-of-bounds.
2599 * Note that we return a @c const @c T* rather than a reference.
2600 */
2601template <class T>
2602inline
2603const T* DATAVECTOR::at (size_type n) const
2604{
2605 return m_pCont.at(n);
2606}
2607
2608
2609/**
2610 * @brief Access an element, as an lvalue.
2611 * @param n Array index to access.
2612 * @return Proxy to the element at @a n.
2613 *
2614 * Will raise @c std::out_of_range if the index is out-of-bounds.
2615 * Note that we return a proxy object rather than a reference;
2616 * the proxy will handle deleting an owned element if it's assigned to.
2617 */
2618template <class T>
2619inline
2620typename DATAVECTOR::ElementProxy DATAVECTOR::at (size_type n)
2621{
2622 // Can't use m_pCont's at here, because we need an iterator.
2623 // So we have to do the bounds check ourselves.
2624 if (n >= size())
2625 CxxUtils::throw_out_of_range (__PRETTY_FUNCTION__, n, this->size(), this);
2626 return ElementProxy (m_pCont.begin() + n, this);
2627}
2628
2629
2630/**
2631 * @brief Access the first element in the collection as an rvalue.
2632 * @return The first element in the collection.
2633 *
2634 * No checking is done to ensure that the container is not empty.
2635 * Note that we return a @c const @c T* rather than a reference.
2636 */
2637template <class T>
2638inline
2639const T* DATAVECTOR::front() const
2640{
2641 return m_pCont.front();
2642}
2643
2644
2645/**
2646 * @brief Access the last element in the collection as an rvalue.
2647 * @return The last element in the collection.
2648 *
2649 * No checking is done to ensure that the container is not empty.
2650 * Note that we return a @c const @c T* rather than a reference.
2651 */
2652template <class T>
2653inline
2654const T* DATAVECTOR::back() const
2655{
2656 return m_pCont.back();
2657}
2658
2659
2660/**
2661 * @brief Access the first element in the collection as an lvalue.
2662 * @return Proxy to the first element in the collection.
2663 *
2664 * No checking is done to ensure that the container is not empty.
2665 * Note that we return a proxy object rather than a reference;
2666 * the proxy will handle deleting an owned element if it's assigned to.
2667 */
2668template <class T>
2669inline
2670typename DATAVECTOR::ElementProxy DATAVECTOR::front ()
2671{
2672 return ElementProxy (m_pCont.begin(), this);
2673}
2674
2675
2676/**
2677 * @brief Access the last element in the collection as an lvalue.
2678 * @return Proxy to the last element in the collection.
2679 *
2680 * No checking is done to ensure that the container is not empty.
2681 * Note that we return a proxy object rather than a reference;
2682 * the proxy will handle deleting an owned element if it's assigned to.
2683 */
2684template <class T>
2685inline
2686typename DATAVECTOR::ElementProxy DATAVECTOR::back ()
2687{
2688 return ElementProxy (m_pCont.end()-1, this);
2689}
2690
2691
2692//=== Iterator creation.
2693
2694
2695/**
2696 * @brief Return a @c const_iterator pointing at the beginning
2697 * of the collection.
2698 * @return A @c const_iterator.
2699 *
2700 * Note that dereferencing the iterator will yield a @c const @c T* rather
2701 * than a reference.
2702 */
2703template <class T>
2704inline
2705typename DATAVECTOR::const_iterator DATAVECTOR::begin() const noexcept
2706{
2707 return m_pCont.begin();
2708}
2709
2710
2711/**
2712 * @brief Return a @c const_iterator pointing past the end
2713 * of the collection.
2714 * @return A @c const_iterator.
2715 *
2716 * Note that dereferencing the iterator will yield a @c const @c T* rather
2717 * than a reference.
2718 */
2719template <class T>
2720inline
2721typename DATAVECTOR::const_iterator DATAVECTOR::end() const noexcept
2722{
2723 return m_pCont.end();
2724}
2725
2726
2727/**
2728 * @brief Return an @c iterator pointing at the beginning
2729 * of the collection.
2730 * @return An @c iterator.
2731 *
2732 * Note that dereferencing the iterator will yield a proxy rather
2733 * than a reference; the proxy will handle deleting an owned element
2734 * if it's assigned to.
2735 */
2736template <class T>
2737inline
2738typename DATAVECTOR::iterator DATAVECTOR::begin() noexcept
2739{
2740 return iterator (m_pCont.begin(), this);
2741}
2742
2743
2744/**
2745 * @brief Return an @c iterator pointing past the end
2746 * of the collection.
2747 * @return An @c iterator.
2748 *
2749 * Note that dereferencing the iterator will yield a proxy rather
2750 * than a reference; the proxy will handle deleting an owned element
2751 * if it's assigned to.
2752 */
2753template <class T>
2754inline
2755typename DATAVECTOR::iterator DATAVECTOR::end() noexcept
2756{
2757 return iterator (m_pCont.end(), this);
2758}
2759
2760
2761/**
2762 * @brief Return a @c const_reverse_iterator pointing past the end
2763 * of the collection.
2764 * @return A @c const_reverse_iterator.
2765 *
2766 * Note that dereferencing the iterator will yield a @c const @c T* rather
2767 * than a reference.
2768 */
2769template <class T>
2770inline
2771typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rbegin() const noexcept
2772{
2773 return const_reverse_iterator (m_pCont.end());
2774}
2775
2776
2777/**
2778 * @brief Return a @c const_reverse_iterator pointing at the beginning
2779 * of the collection.
2780 * @return A @c const_reverse_iterator.
2781 *
2782 * Note that dereferencing the iterator will yield a @c const @c T* rather
2783 * than a reference.
2784 */
2785template <class T>
2786inline
2787typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rend() const noexcept
2788{
2789 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2790}
2791
2792
2793/**
2794 * @brief Return a @c reverse_iterator pointing past the end
2795 * of the collection.
2796 * @return A @c reverse_iterator.
2797 *
2798 * Note that dereferencing the iterator will yield a proxy rather
2799 * than a reference; the proxy will handle deleting an owned element
2800 * if it's assigned to.
2801 */
2802template <class T>
2803inline
2804typename DATAVECTOR::reverse_iterator DATAVECTOR::rbegin() noexcept
2805{
2806 return reverse_iterator(iterator (m_pCont.end(), this));
2807}
2808
2809
2810/**
2811 * @brief Return a @c reverse_iterator pointing at the beginning
2812 * of the collection.
2813 * @return A @c reverse_iterator.
2814 *
2815 * Note that dereferencing the iterator will yield a proxy rather
2816 * than a reference; the proxy will handle deleting an owned element
2817 * if it's assigned to.
2818 */
2819template <class T>
2820inline
2821typename DATAVECTOR::reverse_iterator DATAVECTOR::rend() noexcept
2822{
2823 return reverse_iterator(iterator (m_pCont.begin(), this));
2824}
2825
2826
2827/**
2828 * @brief Return a @c const_iterator pointing at the beginning
2829 * of the collection.
2830 * @return A @c const_iterator.
2831 *
2832 * Note that dereferencing the iterator will yield a @c const @c T* rather
2833 * than a reference.
2834 */
2835template <class T>
2836inline
2837typename DATAVECTOR::const_iterator DATAVECTOR::cbegin() const noexcept
2838{
2839 return m_pCont.begin();
2840}
2841
2842
2843/**
2844 * @brief Return a @c const_iterator pointing past the end
2845 * of the collection.
2846 * @return A @c const_iterator.
2847 *
2848 * Note that dereferencing the iterator will yield a @c const @c T* rather
2849 * than a reference.
2850 */
2851template <class T>
2852inline
2853typename DATAVECTOR::const_iterator DATAVECTOR::cend() const noexcept
2854{
2855 return m_pCont.end();
2856}
2857
2858
2859/**
2860 * @brief Return a @c const_reverse_iterator pointing past the end
2861 * of the collection.
2862 * @return A @c const_reverse_iterator.
2863 *
2864 * Note that dereferencing the iterator will yield a @c const @c T* rather
2865 * than a reference.
2866 */
2867template <class T>
2868inline
2869typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crbegin() const noexcept
2870{
2871 return const_reverse_iterator (m_pCont.end());
2872}
2873
2874
2875/**
2876 * @brief Return a @c const_reverse_iterator pointing at the beginning
2877 * of the collection.
2878 * @return A @c const_reverse_iterator.
2879 *
2880 * Note that dereferencing the iterator will yield a @c const @c T* rather
2881 * than a reference.
2882 */
2883template <class T>
2884inline
2885typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crend() const noexcept
2886{
2887 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2888}
2889
2890
2891//=== Insertion operations.
2892
2893
2894/**
2895 * @brief Add an element to the end of the collection.
2896 * @param pElem The element to add to the collection.
2897 *
2898 * The container's ownership policy will determine if it takes ownership
2899 * of the new element.
2900 *
2901 * Note: this method may only be called using the most derived
2902 * @c DataVector in the hierarchy.
2903 *
2904 * Returns the pushed pointer.
2905 */
2906template <class T>
2907inline
2908typename DATAVECTOR::value_type
2909DATAVECTOR::push_back(value_type pElem)
2910{
2911 // Ensure we're not being called via a base class.
2912 testInsert ("push_back");
2913 m_pCont.push_back(pElem);
2914 SG::AuxVectorBase::resize<DataVector> (this->size());
2915 if (pElem && this->trackIndices())
2916 this->moveAuxNoClear (this->size()-1, pElem);
2917 return pElem;
2918}
2919
2920
2921/**
2922 * @brief Add an element to the end of the collection.
2923 * @param pElem The element to add to the collection.
2924 *
2925 * The container must be an owning container.
2926 *
2927 * Note: this method may only be called using the most derived
2928 * @c DataVector in the hierarchy.
2929 *
2930 * Returns the pushed pointer.
2931 */
2932template <class T>
2933inline
2934typename DATAVECTOR::value_type
2935DATAVECTOR::push_back(std::unique_ptr<base_value_type> pElem)
2936{
2937 // Container must own its elements.
2938 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2939 SG::throwExcNonowningContainer();
2940
2941 // Ensure we're not being called via a base class.
2942 testInsert ("push_back");
2943 value_type ptr = pElem.release();
2944 m_pCont.push_back(ptr);
2945 SG::AuxVectorBase::resize<DataVector> (this->size());
2946 if (ptr && this->trackIndices())
2947 this->moveAuxNoClear (this->size()-1, ptr);
2948 return ptr;
2949}
2950
2951
2952/**
2953 * @brief Create and add a number of new elements to the end of the container.
2954 * @param n The number of new elements to add.
2955 * @param alloc Functional to call to allocate a new element to push.
2956 * Should be callable like <code>T* = alloc();</code>
2957 * For example:
2958 *@code
2959 * dv.push_new (n, [](){ return new Foo; });
2960 @endcode
2961 * It may also be useful to allocate from a @c DataPool.
2962 *
2963 * Note: this method may only be called using the most derived
2964 * @c DataVector in the hierarchy.
2965 *
2966 * Returns the original size of the vector.
2967 */
2968template <class T>
2969template <CxxUtils::detail::AllocationFunction<T> F>
2970auto
2971DATAVECTOR::push_new(size_type n, F alloc) -> size_type
2972{
2973 // Ensure we're not being called via a base class.
2974 testInsert ("push_new");
2975 bool trackIndices = this->trackIndices();
2976
2977 size_t sz = this->m_pCont.size();
2978 this->m_pCont.resize (sz + n);
2979 SG::AuxVectorBase::resize<DataVector> (this->size());
2980 for (size_t i = 0; i < n; i++) {
2981 T* p = alloc();
2982 if (!p) std::abort();
2983 this->m_pCont[sz+i] = p;
2984 if (trackIndices) {
2985 this->moveAuxNoClear (sz+i, p);
2986 }
2987 }
2988 return sz;
2989}
2990
2991
2992/**
2993 * @brief Add an element to the end of the collection.
2994 * @param pElem The element to add to the collection.
2995 *
2996 * The container's ownership policy will determine if it takes ownership
2997 * of the new element.
2998 *
2999 * Note: this method may only be called using the most derived
3000 * @c DataVector in the hierarchy.
3001 *
3002 * For @c DataVector, this is like the same as @c push_back, and
3003 * it returns the pushed element.
3004 * It's included just for interface compatibility with `std::vector`.
3005 */
3006template <class T>
3007inline
3008typename DATAVECTOR::value_type
3009DATAVECTOR::emplace_back(value_type pElem)
3010{
3011 return this->push_back (pElem);
3012}
3013
3014
3015/**
3016 * @brief Add a new element to the collection.
3017 * @param position Iterator before which the element will be added.
3018 * @param pElem The element to add to the collection.
3019 * @return An iterator that points to the inserted data.
3020 *
3021 * The container's ownership policy will determine if it takes ownership
3022 * of the new element.
3023 *
3024 * Note: this method may only be called using the most derived
3025 * @c DataVector in the hierarchy.
3026 */
3027template <class T>
3028inline
3029typename DATAVECTOR::iterator
3030DATAVECTOR::insert(iterator position, value_type pElem)
3031{
3032 // Ensure we're not being called via a base class.
3033 testInsert ("insert");
3034 iterator ret (m_pCont.insert(position.base(), pElem), this);
3035 this->shift (ret - this->begin(), 1);
3036 if (this->trackIndices())
3037 this->moveAuxNoClear (ret-this->begin(), pElem);
3038 return ret;
3039}
3040
3041
3042/**
3043 * @brief Add a new element to the collection.
3044 * @param position Iterator before which the element will be added.
3045 * @param pElem The element to add to the collection.
3046 * @return An iterator that points to the inserted data.
3047 *
3048 * The container must be an owning container.
3049 *
3050 * Note: this method may only be called using the most derived
3051 * @c DataVector in the hierarchy.
3052 */
3053template <class T>
3054inline
3055typename DATAVECTOR::iterator
3056DATAVECTOR::insert(iterator position, std::unique_ptr<base_value_type> pElem)
3057{
3058 // Container must own its elements.
3059 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3060 SG::throwExcNonowningContainer();
3061
3062 // Ensure we're not being called via a base class.
3063 testInsert ("insert");
3064 value_type ptr = pElem.release();
3065 iterator ret (m_pCont.insert(position.base(), ptr), this);
3066 this->shift (ret - this->begin(), 1);
3067 if (this->trackIndices())
3068 this->moveAuxNoClear (ret-this->begin(), ptr);
3069 return ret;
3070}
3071
3072
3073/**
3074 * @brief Add a new element to the collection.
3075 * @param position Iterator before which the element will be added.
3076 * @param pElem The element to add to the collection.
3077 * @return An iterator that points to the inserted data.
3078 *
3079 * The container's ownership policy will determine if it takes ownership
3080 * of the new element.
3081 *
3082 * Note: this method may only be called using the most derived
3083 * @c DataVector in the hierarchy.
3084 *
3085 * For @c DataVector, this is just the same as @c insert.
3086 * It's included just for interface compatibility with `std::vector`.
3087 */
3088template <class T>
3089inline
3090typename DATAVECTOR::iterator
3091DATAVECTOR::emplace(iterator position, value_type pElem)
3092{
3093 return this->insert (position, pElem);
3094}
3095
3096
3097/**
3098 * @brief Add a group of new elements to the collection.
3099 * @param position Iterator before which the element will be added.
3100 * @param first The start of the range to put in the container.
3101 * @param last The end of the range to put in the container.
3102 *
3103 * The container's ownership policy will determine if it takes ownership
3104 * of the new element.
3105 *
3106 * Note: this method may only be called using the most derived
3107 * @c DataVector in the hierarchy.
3108 *
3109 * This overload is for the case where the iterator value type
3110 * is convertible to T*.
3111 */
3112template <class T>
3113template <class InputIterator,
3114 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
3115inline
3116void
3117DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3118{
3119 static_assert (std::is_same_v<T*, typename DATAVECTOR::value_type>);
3120 // Ensure we're not being called via a base class.
3121 testInsert ("insert");
3122 size_t idx = position - this->begin();
3123 size_t old_sz = this->m_pCont.size();
3124 m_pCont.insert(position.base(), first, last);
3125 size_t n = this->m_pCont.size() - old_sz;
3126 this->shift (idx, n);
3127 this->moveAux (idx, first, last, false, true);
3128}
3129
3130
3131/**
3132 * @brief Add a group of new elements to the collection.
3133 * @param position Iterator before which the element will be added.
3134 * @param first The start of the range to put in the container.
3135 * @param last The end of the range to put in the container.
3136 *
3137 * The container's ownership policy will determine if it takes ownership
3138 * of the new element.
3139 *
3140 * Note: this method may only be called using the most derived
3141 * @c DataVector in the hierarchy.
3142 *
3143 * This overload is for the case where the iterator value type
3144 * is convertible to unique_ptr<T>.
3145 */
3146template <class T>
3147template <class InputIterator,
3148 DataVector_detail::enable_if_up_itr<InputIterator, T> >
3149inline
3150void
3151DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3152{
3153 // Ensure we're not being called via a base class.
3154 testInsert ("insert");
3155 size_t idx = position - this->begin();
3156 size_t old_sz = this->m_pCont.size();
3157 using CxxUtils::releasing_iterator;
3158 m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
3159 size_t n = this->m_pCont.size() - old_sz;
3160 this->shift (idx, n);
3161 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
3162}
3163
3164
3165/**
3166 * @brief Add a group of new elements to the collection.
3167 * @param position Iterator before which the element will be added.
3168 * @param l An initializer list.
3169 *
3170 * The container's ownership policy will determine if it takes ownership
3171 * of the new element.
3172 *
3173 * Note: this method may only be called using the most derived
3174 * @c DataVector in the hierarchy.
3175 */
3176template <class T>
3177inline
3178void
3179DATAVECTOR::insert (iterator position, std::initializer_list<value_type> l)
3180{
3181 this->insert (position, l.begin(), l.end());
3182}
3183
3184
3185/**
3186 * @brief Insert the contents of another @c DataVector,
3187 * with auxiliary data copied via move semantics.
3188 * @param position Iterator before which the new elements will be added.
3189 * @param other The vector to add.
3190 *
3191 * The ownership mode of this vector must be the same as @c other;
3192 * otherwise, an exception will be thrown.
3193 *
3194 * If both vectors are view vectors, then this is the same
3195 * as <code> insert (position, other.begin(), other.end()) </code>.
3196 *
3197 * Otherwise, the elements from @c other will be inserted into this vector.
3198 * This vector will take ownership of the elements, and the ownership
3199 * mode of @c other will be changed to @c VIEW_ELEMENTS.
3200 * Auxiliary data for these elements will be transferred,
3201 * using move semantics if possible. (Thus, the auxiliary store
3202 * for @c other may be modified and must not be locked.)
3203 * Finally, the auxiliary store pointer for @c other will be cleared
3204 * (but the store itself will not be deleted since it's not owned
3205 * by the vector).
3206 *
3207 * Note: this method may only be called using the most derived
3208 * @c DataVector in the hierarchy.
3209 */
3210template <class T>
3211void
3212DATAVECTOR::insertMove (iterator position, DataVector& other)
3213{
3214 if (this->m_ownPolicy != other.ownPolicy())
3215 throw SG::ExcInsertMoveOwnershipMismatch();
3216
3217 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
3218 this->insert (position, other.begin(), other.end());
3219 return;
3220 }
3221
3222 testInsert ("insertMove");
3223 size_t pos = position.base() - this->m_pCont.begin();
3224 this->m_pCont.insert (position.base(), other.begin(), other.end());
3225 this->setIndices (this->begin()+pos, this->end(), pos);
3226 other.m_ownPolicy = SG::VIEW_ELEMENTS;
3227
3228 SG::IAuxStore* otherStore = other.getStore();
3229 if (otherStore) {
3230 SG::IAuxStore* store = this->getStore();
3231 if (store) {
3232 if (!store->insertMove (pos, *otherStore))
3233 this->clearCache();
3234 }
3235 else if (this->hasStore())
3236 throw SG::ExcConstAuxData ("insertMove");
3237 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
3238 }
3239 else if (other.hasStore())
3240 throw SG::ExcConstAuxData ("insertMove");
3241}
3242
3243
3244//=== Erasure operations.
3245
3246
3247/**
3248 * @brief Remove element at a given position.
3249 * @param position Iterator pointing to the element to be removed.
3250 * @return An iterator pointing to the next element (or @c end()).
3251 *
3252 * If the container owns its elements, then the pointed-to element
3253 * will be deleted.
3254 */
3255template <class T>
3256inline
3257typename DATAVECTOR::iterator DATAVECTOR::erase(iterator position)
3258{
3259 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3260 this->clearIndex (position);
3261 iterator ret (this->erase_base (position.base()), this);
3262 this->shift (ret - this->begin() + 1, -1);
3263 return ret;
3264}
3265
3266
3267/**
3268 * @brief Remove a range of elements.
3269 * @param first Iterator pointing to the first element to be removed.
3270 * @param last Iterator pointing one past the last element to be removed.
3271 * @return An iterator pointing to the element pointed to by @a last
3272 * prior to erasing (or @c end()).
3273 *
3274 * If the container owns its elements, then the removed elements
3275 * will be deleted. Any duplicates will be removed in this process,
3276 * but don't rely on this.
3277 */
3278template <class T>
3279inline
3280typename DATAVECTOR::iterator DATAVECTOR::erase(iterator first, iterator last)
3281{
3282 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3283 this->clearIndices (first, last);
3284 iterator ret (this->erase_base (first.base(), last.base()), this);
3285 this->shift (ret - this->begin() + (last-first), -(last-first));
3286 return ret;
3287}
3288
3289
3290/**
3291 * @brief Remove the last element from the collection.
3292 *
3293 * If the container owns its elements, then the removed element
3294 * will be deleted.
3295 */
3296template <class T>
3297void DATAVECTOR::pop_back()
3298{
3299 if (!m_pCont.empty()) {
3300 if (m_ownPolicy == SG::OWN_ELEMENTS)
3301 this->doDelete (m_pCont.back());
3302 else
3303 this->clearIndex (m_pCont.end() - 1);
3304 m_pCont.pop_back();
3305 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
3306 }
3307}
3308
3309
3310/**
3311 * @brief Erase all the elements in the collection.
3312 *
3313 * If the container owns its elements, then the removed elements
3314 * will be deleted. Any duplicates will be removed in this process,
3315 * but don't rely on this.
3316 */
3317template <class T>
3318inline
3319void DATAVECTOR::clear()
3320{
3321 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3322 this->clearIndices (begin(), end());
3323 this->erase_base (m_pCont.begin(), m_pCont.end());
3324 SG::AuxVectorBase::resize<DataVector> (0);
3325}
3326
3327
3328//=== Swap and sort.
3329
3330
3331/**
3332 * @brief Swap this collection with another.
3333 * @param rhs The collection with which to swap.
3334 *
3335 * Ownership is swapped along with the collection content.
3336 *
3337 * Note: this method may only be called using the most-derived
3338 * @c DataVector in the hierarchy. The @a rhs must also be
3339 * referenced using the most-derived @c DataVector.
3340 *
3341 * Warning: If this container has auxiliary data, then this
3342 * is an O(N) operation, not O(1).
3343 */
3344template <class T>
3345void DATAVECTOR::swap(DataVector& rhs)
3346{
3347 testInsert ("swap");
3348 rhs.testInsert ("swap");
3349 std::swap(m_ownPolicy, rhs.m_ownPolicy);
3350 SG::AuxVectorBase::swap (rhs);
3351 m_pCont.swap(rhs.m_pCont);
3352 std::swap (this->m_deleter, rhs.m_deleter);
3353 this->setIndices (this->begin(), this->end());
3354 rhs.setIndices (rhs.begin(), rhs.end());
3355}
3356
3357
3358/**
3359 * @brief Swap the referents of two @c DataVector iterators.
3360 * @param a The first iterator for the swap.
3361 * @param b The second iterator for the swap.
3362 */
3363template <class T>
3364void DATAVECTOR::iter_swap (iterator a, iterator b)
3365{
3366 if (a.ownPolicy() != b.ownPolicy()) {
3367 throw SG::ExcBadIterSwap();
3368 }
3369 a.testInsert ("iter_swap");
3370 b.testInsert ("iter_swap");
3371 std::iter_swap (a.base(), b.base());
3372 DataVector* acont = a.container();
3373 DataVector* bcont = b.container();
3374 if (typename SG::AuxStore_traits<DataVector>::flag())
3375 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
3376 b.base() - bcont->stdcont().begin(),
3377 *a.base(),
3378 *b.base(),
3379 bcont);
3380}
3381
3382
3383/**
3384 * @brief Sort the container.
3385 *
3386 * This just sorts by pointer value, so it's probably not very useful.
3387 */
3388template <class T>
3389void DATAVECTOR::sort()
3390{
3391 std::sort(m_pCont.begin(), m_pCont.end());
3392 this->resortAux (this->begin(), this->end());
3393}
3394
3395
3396/**
3397 * @brief Sort the container with a user-specified comparison operator.
3398 * @param comp Functional to compare two values.
3399 */
3400template <class T>
3401template <class COMPARE>
3402void DATAVECTOR::sort(COMPARE comp)
3403{
3404 std::sort(m_pCont.begin(), m_pCont.end(), comp);
3405 this->resortAux (this->begin(), this->end());
3406}
3407
3408
3409//=== Non-standard operations.
3410
3411
3412/**
3413 * @brief Swap one element out of the container.
3414 * @param index Index of the element in the container to swap.
3415 * @param newElement New element to put in the container.
3416 * May be 0.
3417 * @param oldElem Reference to receive the element removed from the
3418 * container.
3419 *
3420 * Reference @a oldElem is initialized with element @a index of the
3421 * collection (no bounds checking). Then element @a index is set
3422 * to @newElem. If the collection owns its elements, then it will
3423 * take ownership of @a newElem and release (without deleting)
3424 * the element returned through @a oldElem.
3425 *
3426 * Note: this method may only be called using the most derived
3427 * @c DataVector in the hierarchy.
3428 */
3429template <class T>
3430void
3431DATAVECTOR::swapElement (size_type index,
3432 value_type newElem,
3433 reference oldElem)
3434{
3435 testInsert ("swapElement");
3436 oldElem = m_pCont[index];
3437 this->clearIndex (iterator (m_pCont.begin() + index, this));
3438 m_pCont[index] = newElem;
3439 this->moveAux (index, newElem);
3440}
3441
3442
3443/**
3444 * @brief Swap one element out of the container.
3445 * @param pos The element in the container to swap.
3446 * @param newElem New element to put in the container.
3447 * May be 0.
3448 * @param oldElem Reference to receive the element removed from the
3449 * container.
3450 *
3451 * Reference @a oldElem is initialized with element @a pos of the
3452 * collection (no bounds checking). Then element @a index is set
3453 * to @c newElem. If the collection owns its elements, then it will
3454 * take ownership of @a newElem and release (without deleting)
3455 * the element returned through @a oldElem.
3456 *
3457 * Note: this method may only be called using the most derived
3458 * @c DataVector in the hierarchy.
3459 */
3460template <class T>
3461void
3462DATAVECTOR::swapElement (iterator pos,
3463 value_type newElem,
3464 reference oldElem)
3465{
3466 testInsert ("swapElement");
3467 oldElem = *pos.base();
3468 this->clearIndex (pos);
3469 *pos.base() = newElem;
3470 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
3471}
3472
3473
3474/**
3475 * @brief Swap one element out of the container.
3476 * @param index Index of the element in the container to swap.
3477 * @param newElement New element to put in the container.
3478 * May be 0.
3479 * @param oldElem Reference to receive the element removed from the
3480 * container.
3481 *
3482 * Reference @a oldElem is initialized with element @a index of the
3483 * collection (no bounds checking). Then element @a index is set
3484 * to @newElem.
3485 *
3486 * The collection must own its elements to use its interface.
3487 * The collection will take ownership of @c newElem and will return
3488 * ownership of @c oldElem.
3489 *
3490 * Note: this method may only be called using the most derived
3491 * @c DataVector in the hierarchy.
3492 */
3493template <class T>
3494void
3495DATAVECTOR::swapElement (size_type index,
3496 std::unique_ptr<base_value_type> newElem,
3497 std::unique_ptr<base_value_type>& oldElem)
3498{
3499 // Container must own its elements.
3500 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3501 SG::throwExcNonowningContainer();
3502
3503 testInsert ("swapElement");
3504 oldElem = std::unique_ptr<base_value_type> (m_pCont[index]);
3505 this->clearIndex (iterator (m_pCont.begin() + index, this));
3506 value_type ptr = newElem.release();
3507 m_pCont[index] = ptr;
3508 this->moveAux (index, ptr);
3509}
3510
3511
3512/**
3513 * @brief Swap one element out of the container.
3514 * @param pos The element in the container to swap.
3515 * @param newElem New element to put in the container.
3516 * May be 0.
3517 * @param oldElem Reference to receive the element removed from the
3518 * container.
3519 *
3520 * Reference @a oldElem is initialized with element @a pos of the
3521 * collection (no bounds checking). Then element @a index is set
3522 * to @c newElem.
3523 *
3524 * The collection must own its elements to use its interface.
3525 * The collection will take ownership of @c newElem and will return
3526 * ownership of @c oldElem.
3527 *
3528 * Note: this method may only be called using the most derived
3529 * @c DataVector in the hierarchy.
3530 */
3531template <class T>
3532void
3533DATAVECTOR::swapElement (iterator pos,
3534 std::unique_ptr<base_value_type> newElem,
3535 std::unique_ptr<base_value_type>& oldElem)
3536{
3537 // Container must own its elements.
3538 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3539 SG::throwExcNonowningContainer();
3540
3541 testInsert ("swapElement");
3542 oldElem = std::unique_ptr<base_value_type> (*pos.base());
3543 this->clearIndex (pos);
3544 value_type ptr = newElem.release();
3545 *pos.base() = ptr;
3546 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
3547}
3548
3549
3550/**
3551 * @brief Return the underlying @c std::vector of the container.
3552 * @return Reference to the @c std::vector actually holding the collection.
3553 *
3554 * Note that @c DataVector<T>::stdcont does not necessarily return
3555 * a @c std::vector<T*> if @c DataVector inheritance is being used.
3556 */
3557template <class T>
3558inline
3559const typename DATAVECTOR::PtrVector& DATAVECTOR::stdcont() const
3560{
3561 return m_pCont;
3562}
3563
3564
3565/**
3566 * @brief Return the ownership policy setting for this container.
3567 */
3568template <class T>
3569inline
3570SG::OwnershipPolicy DATAVECTOR::ownPolicy() const
3571{
3572 return m_ownPolicy;
3573}
3574
3575
3576/**
3577 * @brief Erase all the elements in the collection, and reset
3578 * the ownership mode.
3579 * @param ownPolicy The new ownership policy of the container.
3580 * @param trackIndices The index tracking policy.
3581 *
3582 * If the container owns its elements, then the removed elements
3583 * will be deleted. Any duplicates will be removed in this process,
3584 * but don't rely on this.
3585 */
3586template <class T>
3587void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy)
3588{
3589 clear();
3590 m_ownPolicy = ownPolicy;
3591 this->template initAuxVectorBase<DataVector> (ownPolicy,
3592 SG::DEFAULT_TRACK_INDICES);
3593}
3594
3595
3596/**
3597 * @brief Erase all the elements in the collection, and reset
3598 * the ownership mode.
3599 * @param ownPolicy The new ownership policy of the container.
3600 * @param trackIndices The index tracking policy.
3601 *
3602 * If the container owns its elements, then the removed elements
3603 * will be deleted. Any duplicates will be removed in this process,
3604 * but don't rely on this.
3605 */
3606template <class T>
3607void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy,
3608 SG::IndexTrackingPolicy trackIndices)
3609{
3610 clear();
3611 m_ownPolicy = ownPolicy;
3612 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
3613}
3614
3615
3616/**
3617 * @brief Return the DV/DL info struct for this class.
3618 *
3619 * This can be used to make sure that it's instantiated.
3620 */
3621template <class T>
3622const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo()
3623{
3624 static const DataModel_detail::DVLInfo<DataVector<T, DataModel_detail::NoBase> > info;
3625 return info;
3626}
3627
3628
3629/**
3630 * @brief Erase all the elements in the collection, and change
3631 * how elements are to be deleted.
3632 * @param deleter Object to be used to delete object.
3633 * (The DataVector does not take ownership.)
3634 * Passing nullptr will change back to the default.
3635 *
3636 * If the container owns its elements, then the removed elements
3637 * will be deleted. Any duplicates will be removed in this process,
3638 * but don't rely on this.
3639 * After the current elements are deleted, the Deleter object is changed.
3640 */
3641template <class T>
3642void DATAVECTOR::clear (std::unique_ptr<Deleter> deleter)
3643{
3644 this->clear();
3645 delete this->m_deleter;
3646 this->m_deleter = deleter.release();
3647}
3648
3649
3650/**
3651 * @brief Return the DV/DL info struct for this class.
3652 *
3653 * This can be used to make sure that it's instantiated.
3654 */
3655template <class T>
3656const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo_v() const
3657{
3658 return DATAVECTOR::dvlinfo();
3659}
3660
3661
3662/**
3663 * @brief Return the offset of a base @c DataVector class.
3664 * @param ti @c std::type_info of the desired class.
3665 *
3666 * If @c ti represents a @c DataVector base class of this one,
3667 * then return the offset of that base class. Otherwise, return -1.
3668 *
3669 * This function is here due to limitations of root 6, which can't
3670 * calculate these offsets correctly from the dictionary if
3671 * virtual derivation is used.
3672 */
3673template <class T>
3674int DATAVECTOR::baseOffset (const std::type_info& ti)
3675{
3676 if (typeid(DataVector) == ti)
3677 return 0;
3678 return -1;
3679}
3680
3681
3682/**
3683 * @brief Convert to @c AuxVectorBase.
3684 *
3685 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
3686 * Present in @c DataVector as well for consistency.
3687 */
3688template <class T>
3689inline
3690const SG::AuxVectorBase& DATAVECTOR::auxbase() const
3691{
3692 return *this;
3693}
3694
3695
3696//=== Internal operations.
3697
3698
3699/**
3700 * @brief Helper for @c baseOffset.
3701 * @param p Pointer to the start of the top-level object.
3702 * @param dv Reference to the DataVector object.
3703 * @param ti @c std::type_info of the desired class.
3704 *
3705 * If @c ti represents a @c DataVector base class of this one,
3706 * then return the offset of that base class. Otherwise, return -1.
3707 *
3708 */
3709template <class T>
3710int DATAVECTOR::baseOffset1 (const char* p, const DataVector& dv,
3711 const std::type_info& ti)
3712{
3713 if (typeid(DataVector) == ti)
3714 return reinterpret_cast<const char*>(&dv) - p;
3715 return -1;
3716}
3717
3718
3719/**
3720 * @brief Reset indices / reorder aux data after elements have been permuted.
3721 * @param beg Start of the range of elements to process.
3722 * @param end End of the range of elements to process.
3723 *
3724 * Call this after some operation that has permuted the elements in the
3725 * container (such as sort). The index information in the elements
3726 * will be used to permute all auxiliary data in the same way.
3727 * Finally, all the indices will be reset in the correct order.
3728 */
3729template <class T>
3730void DATAVECTOR::resortAux (iterator beg, iterator end)
3731{
3732 if (typename SG::AuxStore_traits<DataVector>::flag() &&
3733 beg >= this->begin() && end <= this->end())
3734 {
3735 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
3736 }
3737}
3738
3739
3740/**
3741 * @brief Handle element assignment.
3742 * @param pos Position in the container to assign.
3743 * @param newElem The new element to assign.
3744 *
3745 * The old element is freed if this container owns elements.
3746 * Auxiliary data are copied if appropriate.
3747 */
3748template <class T>
3749void DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3750 value_type newElem)
3751{
3752 testInsert ("assignElement");
3753 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3754 this->doDelete (*pos);
3755 else
3756 this->clearIndex (iterator (pos, this));
3757 *pos = newElem;
3758 this->moveAux (pos - this->m_pCont.begin(), newElem);
3759}
3760
3761
3762/**
3763 * @brief Handle element assignment.
3764 * @param pos Position in the container to assign.
3765 * @param newElem The new element to assign.
3766 *
3767 * The container must own its elements.
3768 * Auxiliary data are copied if appropriate.
3769 */
3770template <class T>
3771void
3772DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3773 std::unique_ptr<base_value_type> newElem)
3774{
3775 // Container must own its elements.
3776 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3777 SG::throwExcNonowningContainer();
3778
3779 testInsert ("assignElement");
3780 this->doDelete (*pos);
3781 value_type ptr = newElem.release();
3782 *pos = ptr;
3783 this->moveAux (pos - this->m_pCont.begin(), ptr);
3784}
3785
3786
3787/**
3788 * @brief Handle element assignment from a base pointer.
3789 * @param pos Position in the container to assign.
3790 * @param newElem The new element to assign.
3791 *
3792 * The old element is freed if this container owns elements.
3793 * Auxiliary data are copied if appropriate.
3794 */
3795template <class T>
3796void DATAVECTOR::assignBaseElement (typename BaseContainer::iterator pos,
3797 typename BaseContainer::value_type newElem)
3798{
3799 testInsert ("assignBaseElement");
3800 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3801 this->doDelete (*pos);
3802 else
3803 this->clearIndex (iterator (pos, this));
3804 *pos = newElem;
3805 if (typename SG::AuxStore_traits<DataVector>::flag())
3806 this->moveAux (pos - this->m_pCont.begin(), newElem);
3807}
3808
3809
3810/**
3811 * @brief Shift the auxiliary elements of the container.
3812 * @param pos The starting index for the shift.
3813 * @param offs The (signed) amount of the shift.
3814 *
3815 * The elements in the container should have already been shifted;
3816 * this operation will then adjust the element indices and also shift
3817 * the elements in the vectors for all aux data items.
3818 * @c offs may be either positive or negative.
3819 *
3820 * If @c offs is positive, then the container is growing.
3821 * The container size should be increased by @c offs,
3822 * the element at @c pos moved to @c pos + @c offs,
3823 * and similarly for following elements.
3824 * The elements between @c pos and @c pos + @c offs should
3825 * be default-initialized.
3826 *
3827 * If @c offs is negative, then the container is shrinking.
3828 * The element at @c pos should be moved to @c pos + @c offs,
3829 * and similarly for following elements.
3830 * The container should then be shrunk by @c -offs elements
3831 * (running destructors as appropriate).
3832 */
3833template <class T>
3834void DATAVECTOR::shift (size_t pos, ptrdiff_t offs)
3835{
3836 SG::AuxVectorBase::shift (*this, pos, offs);
3837}
3838
3839
3840/**
3841 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3842 * @param p The value to convert.
3843 * @return The value as a @c const @c T*.
3844 *
3845 * This is a no-op for the base class.
3846 */
3847template <class T>
3848inline
3849const T* DATAVECTOR::do_cast (const typename PtrVector::value_type p)
3850{
3851 return p;
3852}
3853
3854
3855/**
3856 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3857 * @param p The value to convert.
3858 * @return The value as a @c T*.
3859 *
3860 * This is a no-op for the base class.
3861 */
3862template <class T>
3863inline
3864T* DATAVECTOR::do_cast_nc (typename PtrVector::value_type p)
3865{
3866 return p;
3867}
3868
3869
3870/**
3871 * @brief Find the most-derived @c DataVector class in the hierarchy.
3872 * @return The @c type_info for the class for which this method gets run.
3873 *
3874 * This is used to generate a nice error message when the most-derived
3875 * check for insertions fails.
3876 * Every @c DataVector defines this virtual method, so when it's
3877 * called, the one corresponding to the most-derived @c DataVector
3878 * gets run.
3879 */
3880template <class T>
3881const std::type_info& DATAVECTOR::dv_typeid() const
3882{
3883 return typeid(DataVector);
3884}
3885
3886
3887/**
3888 * @brief Helper for @c erase(). Remove element at a given position.
3889 * @param position Iterator pointing to the element to be removed.
3890 * @return An iterator pointing to the next element (or @c end()).
3891 *
3892 * This function factors out common code between @c erase() in the
3893 * base and derived @c DataVector classes. It deals with the
3894 * @c std::vector iterators directly.
3895 */
3896template <class T>
3897typename DATAVECTOR::PtrVector::iterator
3898DATAVECTOR::erase_base(typename PtrVector::iterator position)
3899{
3900 if (m_ownPolicy == SG::OWN_ELEMENTS && position != m_pCont.end())
3901 this->doDelete (*position);
3902 return m_pCont.erase(position);
3903}
3904
3905
3906/**
3907 * @brief Helper for @c erase(). Remove a range of elements.
3908 * @param first Iterator pointing to the first element to be removed.
3909 * @param last Iterator pointing one past the last element to be removed.
3910 * @return An iterator pointing to the element pointed to by @a last
3911 * prior to erasing (or @c end()).
3912 *
3913 * This function factors out common code between @c erase() in the
3914 * base and derived @c DataVector classes. It deals with the
3915 * @c std::vector iterators directly.
3916 */
3917template <class T>
3918typename DATAVECTOR::PtrVector::iterator
3919DATAVECTOR::erase_base(typename PtrVector::iterator first,
3920 typename PtrVector::iterator last)
3921{
3922 if (first == last) return first;
3923 if (m_ownPolicy == SG::OWN_ELEMENTS) {
3924 typename PtrVector::iterator new_end =
3925 DataVector_detail::remove_duplicates(first, last);
3926 this->doDelete (first, new_end);
3927 }
3928 return m_pCont.erase(first, last);
3929}
3930
3931
3932/**
3933 * @brief Delete an element
3934 * @param p The element to delete.
3935 */
3936template <class T>
3937inline
3938void DATAVECTOR::doDelete (value_type p)
3939{
3940 if (m_deleter) {
3941 m_deleter->doDelete (p);
3942 }
3943 else {
3944 delete p;
3945 }
3946}
3947
3948
3949/**
3950 * @brief Delete a range of elements
3951 * @param first Start of range to delete.
3952 * @param last End of range to delete.
3953 */
3954template <class T>
3955inline
3956void DATAVECTOR::doDelete (typename PtrVector::iterator first,
3957 typename PtrVector::iterator last)
3958{
3959 if (m_deleter) {
3960 m_deleter->doDelete (first, last);
3961 }
3962 else {
3963 for (; first != last; ++first) {
3964 delete *first;
3965 }
3966 }
3967}
3968
3969
3970/**
3971 * @brief Test if we can insert; raise an exception if not.
3972 * @param op Description of the attempted operation.
3973 *
3974 * In order to maintain type-safety, we can only allow insertions
3975 * using the most-derived instance of @c DataVector. This checks
3976 * this by testing the @c m_isMostDerived, which is set by the constructors
3977 * to true only for the most-derived instance.
3978 * If the test fails, we call to potentially out-of-line code to continue.
3979 */
3980template <class T>
3981inline
3982void DATAVECTOR::testInsert (const char* op)
3983{
3984 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
3985 return;
3986 this->testInsertOol (op);
3987}
3988
3989
3990/**
3991 * @brief Test if we can insert; raise an exception if not.
3992 * @param op Description of the attempted operation.
3993 *
3994 * This continues the test of @c testInsert. There is one case
3995 * where @c m_isMostDerived may not be set correctly. If this container
3996 * was made via copy construction, then all the @c m_isMostDerived flags
3997 * will be false. So we call @c setMostDerived to set the flags correctly
3998 * and test again. If the test fails again, then we raise an exception.
3999 */
4000template <class T>
4001void DATAVECTOR::testInsertOol (const char* op)
4002{
4003 this->setMostDerived();
4004 if (!m_isMostDerived)
4005 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
4006}
4007
4008
4009/**
4010 * @brief Clear @c m_isMostDerived for this instance and for all bases.
4011 *
4012 * Called from the constructor after setting @c m_isMostDerived.
4013 */
4014template <class T>
4015inline
4016void DATAVECTOR::clearMostDerived()
4017{
4018 this->m_isMostDerived = false;
4019}
4020
4021
4022/**
4023 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
4024 *
4025 * Called from @c testInsert if the test fails. The flag may not have
4026 * been set if this container was made via copy construction, so set
4027 * it appropriately now so we can test again.
4028 */
4029template <class T>
4030void DATAVECTOR::setMostDerived()
4031{
4032 m_isMostDerived = true;
4033}
4034
4035
4036#undef DATAVECTOR
4037
4038
4039//****************************************************************************
4040// Free function implementations.
4041//
4042
4043
4044/**
4045 * @brief Vector equality comparison.
4046 * @param a A @c DataVector.
4047 * @param b A @c DataVector of the same type as @a b.
4048 * @return True iff the size and elements of the vectors are equal.
4049 *
4050 * This is an equivalence relation. It is linear in the size of the
4051 * vectors. Vectors are considered equivalent if their sizes are equal,
4052 * and if corresponding elements compare equal.
4053 */
4054template <class T>
4055bool operator== (const DataVector<T>& a, const DataVector<T>& b)
4056{
4057 return a.stdcont() == b.stdcont();
4058}
4059
4060
4061/// Based on operator==
4062template <class T>
4063bool operator!= (const DataVector<T>& a, const DataVector<T>& b)
4064{
4065 return a.stdcont() != b.stdcont();
4066}
4067
4068
4069/**
4070 * @brief Vector ordering relation.
4071 * @param a A @c DataVector.
4072 * @param b A @c DataVector of the same type as @a x.
4073 * @return True iff @a a is lexicographically less than @a b.
4074 *
4075 * This is a total ordering relation. It is linear in the size of the
4076 * vectors. Comparisons are done on the pointer values of the elements.
4077 *
4078 * See @c std::lexicographical_compare() for how the determination is made.
4079 */
4080template <class T>
4081bool operator< (const DataVector<T>& a, const DataVector<T>& b)
4082{
4083 return a.stdcont() < b.stdcont();
4084}
4085
4086
4087/// Based on operator<
4088template <class T>
4089bool operator> (const DataVector<T>& a, const DataVector<T>& b)
4090{
4091 return a.stdcont() > b.stdcont();
4092}
4093
4094
4095/// Based on operator<
4096template <class T>
4097bool operator<= (const DataVector<T>& a, const DataVector<T>& b)
4098{
4099 return a.stdcont() <= b.stdcont();
4100}
4101
4102
4103/// Based on operator<
4104template <class T>
4105bool operator>= (const DataVector<T>& a, const DataVector<T>& b)
4106{
4107 return a.stdcont() >= b.stdcont();
4108}
4109
4110
4111/// See @c DataVector<T, BASE>::swap().
4112template <class T>
4113void swap (DataVector<T>& a, DataVector<T>& b)
4114{
4115 a.swap (b);
4116}
4117
4118
4119/**
4120 * @brief Specialization of @c ClassName for @c DataVector.
4121 *
4122 * This overrides the default implementation of @c ClassName
4123 * to hide @c DataVector's second template parameter.
4124 */
4125template <class T>
4126std::string ClassName<DataVector<T> >::name()
4127{
4128 std::string out = "DataVector<";
4129 out += ClassName<T>::name();
4130 if (out[out.size()-1] == '>')
4131 out += ' ';
4132 out += '>';
4133 return out;
4134}
4135
4136
4137#ifndef XAOD_STANDALONE
4138
4139
4140// Set up initialization of element type BaseInfo
4141namespace DataVector_detail {
4142#define DVLTYPE DataVector
4143#include "AthContainers/tools/DVLEltBaseInfo.icc"
4144#undef DVLTYPE
4145} // namespace DataVector_detail
4146
4147
4148#else
4149
4150
4151namespace DataVector_detail {
4152/// Dummy implementation for the DVLEltBaseInit structure
4153template< class T >
4154struct DVLEltBaseInit {};
4155} // namespace DataVector_detail
4156
4157
4158#endif // not XAOD_STANDALONE
4159
4160
4161
4162// We need to specialize the function that DVLInfo uses to create the container
4163// for DataVector.
4164/**
4165 * @brief Construct a new container.
4166 * @param nreserve Number of elements for which to reserve space.
4167 * (Ignored if not appropriate.)
4168 * @param cont[out] Pointer to the constructed container.
4169 * (Returned via an argument to allow for template
4170 * argument deduction.)
4171 *
4172 * Specialization for DataVector.
4173 */
4174template <class T>
4175void dvl_makecontainer (size_t nreserve, DataVector<T>*& cont)
4176{
4177 cont = new DataVector<T> (SG::VIEW_ELEMENTS);
4178 cont->reserve (nreserve);
4179}