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 this->m_pCont[sz+i] = p;
1145 if (trackIndices) {
1146 this->moveAuxNoClear (sz+i, p);
1147 }
1148 }
1149 return sz;
1150}
1151
1152
1153/**
1154 * @brief Add an element to the end of the collection.
1155 * @param pElem The element to add to the collection.
1156 *
1157 * The container's ownership policy will determine if it takes ownership
1158 * of the new element.
1159 *
1160 * Note: this method may only be called using the most derived
1161 * @c DataVector in the hierarchy.
1162 *
1163 * For @c DataVector, this is like the same as @c push_back, and
1164 * it returns the pushed element.
1165 * It's included just for interface compatibility with `std::vector`.
1166 */
1167template <class T, class BASE>
1168inline
1169typename DataVector<T, BASE>::value_type
1170DataVector<T, BASE>::emplace_back(value_type pElem)
1171{
1172 return this->push_back (pElem);
1173}
1174
1175
1176/**
1177 * @brief Add a new element to the collection.
1178 * @param position Iterator before which the element will be added.
1179 * @param pElem The element to add to the collection.
1180 * @return An iterator that points to the inserted data.
1181 *
1182 * The container's ownership policy will determine if it takes ownership
1183 * of the new element.
1184 *
1185 * Note: this method may only be called using the most derived
1186 * @c DataVector in the hierarchy.
1187 */
1188template <class T, class BASE>
1189typename DataVector<T, BASE>::iterator
1190DataVector<T, BASE>::insert(iterator position, value_type pElem)
1191{
1192 // Ensure we're not being called via a base class.
1193 testInsert ("insert");
1194 iterator ret (this->m_pCont.insert(position.base(), pElem), this);
1195 this->shift (ret - this->begin(), 1);
1196 this->moveAux (ret-this->begin(), pElem, false, true);
1197 return ret;
1198}
1199
1200
1201/**
1202 * @brief Add a new element to the collection.
1203 * @param position Iterator before which the element will be added.
1204 * @param pElem The element to add to the collection.
1205 * @return An iterator that points to the inserted data.
1206 *
1207 * The container must be an owning container.
1208 *
1209 * Note: this method may only be called using the most derived
1210 * @c DataVector in the hierarchy.
1211 */
1212template <class T, class BASE>
1213typename DataVector<T, BASE>::iterator
1214DataVector<T, BASE>::insert(iterator position,
1215 std::unique_ptr<base_value_type> pElem)
1216{
1217 // Container must own its elements.
1218 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1219 SG::throwExcNonowningContainer();
1220
1221 // Ensure we're not being called via a base class.
1222 testInsert ("insert");
1223 value_type ptr = pElem.release();
1224 iterator ret (this->m_pCont.insert(position.base(), ptr), this);
1225 this->shift (ret - this->begin(), 1);
1226 if (this->trackIndices())
1227 this->moveAuxNoClear (ret-this->begin(), ptr);
1228 return ret;
1229}
1230
1231
1232/**
1233 * @brief Add a new element to the collection.
1234 * @param position Iterator before which the element will be added.
1235 * @param pElem The element to add to the collection.
1236 * @return An iterator that points to the inserted data.
1237 *
1238 * The container's ownership policy will determine if it takes ownership
1239 * of the new element.
1240 *
1241 * Note: this method may only be called using the most derived
1242 * @c DataVector in the hierarchy.
1243 *
1244 * For @c DataVector, this is just the same as @c insert.
1245 * It's included just for interface compatibility with `std::vector`.
1246 */
1247template <class T, class BASE>
1248typename DataVector<T, BASE>::iterator
1249DataVector<T, BASE>::emplace(iterator position, value_type pElem)
1250{
1251 return this->insert (position, pElem);
1252}
1253
1254
1255/**
1256 * @brief Add a group of new elements to the collection.
1257 * @param position Iterator before which the element will be added.
1258 * @param first The start of the range to put in the container.
1259 * @param last The end of the range to put in the container.
1260 *
1261 * The container's ownership policy will determine if it takes ownership
1262 * of the new element.
1263 *
1264 * Note: this method may only be called using the most derived
1265 * @c DataVector in the hierarchy.
1266 *
1267 * This overload is for the case where the iterator value type
1268 * is convertible to T*.
1269 */
1270template <class T, class BASE>
1271template <class InputIterator,
1272 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
1273void DataVector<T, BASE>::insert(iterator position,
1274 InputIterator first,
1275 InputIterator last)
1276{
1277 // Make sure that the input iterator can actually be converted
1278 // to a T*. Lets us give a compilation error for this:
1279 // DATAVECTOR_BASE(D, B);
1280 // B* bb[] = ...
1281 // DataVector<D> d;
1282 // d.insert (d.begin(), bb, bb+1);
1283 // which would otherwise compile.
1284 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1285 static_assert (std::is_convertible_v<ittype, const T*>);
1286
1287 // Ensure we're not being called via a base class.
1288 testInsert ("insert");
1289 size_t idx = position - this->begin();
1290 size_t old_sz = this->m_pCont.size();
1291 this->m_pCont.insert(position.base(), first, last);
1292 size_t n = this->m_pCont.size() - old_sz;
1293 this->shift (idx, n);
1294 this->moveAux (idx, first, last, false, true);
1295}
1296
1297
1298/**
1299 * @brief Add a group of new elements to the collection.
1300 * @param position Iterator before which the element will be added.
1301 * @param first The start of the range to put in the container.
1302 * @param last The end of the range to put in the container.
1303 *
1304 * The container's ownership policy will determine if it takes ownership
1305 * of the new element.
1306 *
1307 * Note: this method may only be called using the most derived
1308 * @c DataVector in the hierarchy.
1309 *
1310 * This overload is for the case where the iterator value type
1311 * is convertible to unique_ptr<T>.
1312 */
1313template <class T, class BASE>
1314template <class InputIterator,
1315 DataVector_detail::enable_if_up_itr<InputIterator, T> >
1316void DataVector<T, BASE>::insert(iterator position,
1317 InputIterator first,
1318 InputIterator last)
1319{
1320 // Make sure that the input iterator can actually be converted
1321 // to a T*. Lets us give a compilation error for this:
1322 // DATAVECTOR_BASE(D, B);
1323 // B* bb[] = ...
1324 // DataVector<D> d;
1325 // d.insert (d.begin(), bb, bb+1);
1326 // which would otherwise compile.
1327 using ittype = typename std::iterator_traits<InputIterator>::value_type;
1328 static_assert (std::is_convertible_v<typename ittype::pointer, const T*>);
1329
1330 // Ensure we're not being called via a base class.
1331 testInsert ("insert");
1332 size_t idx = position - this->begin();
1333 size_t old_sz = this->m_pCont.size();
1334 using CxxUtils::releasing_iterator;
1335 this->m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
1336 size_t n = this->m_pCont.size() - old_sz;
1337 this->shift (idx, n);
1338 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
1339}
1340
1341
1342/**
1343 * @brief Add a group of new elements to the collection.
1344 * @param position Iterator before which the element will be added.
1345 * @param l An initializer list.
1346 *
1347 * The container's ownership policy will determine if it takes ownership
1348 * of the new element.
1349 *
1350 * Note: this method may only be called using the most derived
1351 * @c DataVector in the hierarchy.
1352 */
1353template <class T, class BASE>
1354void DataVector<T, BASE>::insert(iterator position,
1355 std::initializer_list<value_type> l)
1356{
1357 insert (position, l.begin(), l.end());
1358}
1359
1360
1361/**
1362 * @brief Insert the contents of another @c DataVector,
1363 * with auxiliary data copied via move semantics.
1364 * @param position Iterator before which the new elements will be added.
1365 * @param other The vector to add.
1366 *
1367 * The ownership mode of this vector must be the same as @c other;
1368 * otherwise, an exception will be thrown.
1369 *
1370 * If both vectors are view vectors, then this is the same
1371 * as <code> insert (position, other.begin(), other.end()) </code>.
1372 *
1373 * Otherwise, the elements from @c other will be inserted into this vector.
1374 * This vector will take ownership of the elements, and the ownership
1375 * mode of @c other will be changed to @c VIEW_ELEMENTS.
1376 * Auxiliary data for these elements will be transferred,
1377 * using move semantics if possible. (Thus, the auxiliary store
1378 * for @c other may be modified and must not be locked.)
1379 * Finally, the auxiliary store pointer for @c other will be cleared
1380 * (but the store itself will not be deleted since it's not owned
1381 * by the vector).
1382 *
1383 * Note: this method may only be called using the most derived
1384 * @c DataVector in the hierarchy.
1385 */
1386template <class T, class BASE>
1387void
1388DataVector<T, BASE>::insertMove (iterator position, DataVector& other)
1389{
1390 if (this->m_ownPolicy != other.ownPolicy())
1391 throw SG::ExcInsertMoveOwnershipMismatch();
1392
1393 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
1394 this->insert (position, other.begin(), other.end());
1395 return;
1396 }
1397
1398 testInsert ("insertMove");
1399 size_t pos = position.base() - this->m_pCont.begin();
1400 this->m_pCont.insert (position.base(), other.begin(), other.end());
1401 this->setIndices (this->begin()+pos, this->end(), pos);
1402 other.m_ownPolicy = SG::VIEW_ELEMENTS;
1403
1404 SG::IAuxStore* otherStore = other.getStore();
1405 if (otherStore) {
1406 SG::IAuxStore* store = this->getStore();
1407 if (store) {
1408 if (!store->insertMove (pos, *otherStore))
1409 this->clearCache();
1410 }
1411 else if (this->hasStore())
1412 throw SG::ExcConstAuxData ("insertMove");
1413 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
1414 }
1415 else if (other.hasStore())
1416 throw SG::ExcConstAuxData ("insertMove");
1417}
1418
1419
1420//=== Erasure operations.
1421
1422
1423/**
1424 * @brief Remove element at a given position.
1425 * @param position Iterator pointing to the element to be removed.
1426 * @return An iterator pointing to the next element (or @c end()).
1427 *
1428 * If the container owns its elements, then the pointed-to element
1429 * will be deleted.
1430 */
1431template <class T, class BASE>
1432typename DataVector<T, BASE>::iterator
1433DataVector<T, BASE>::erase(iterator position)
1434{
1435 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1436 this->clearIndex (position);
1437 iterator ret (this->erase_base (position.base()), this);
1438 this->shift (ret - this->begin() + 1, -1);
1439 return ret;
1440}
1441
1442
1443/**
1444 * @brief Remove a range of elements.
1445 * @param first Iterator pointing to the first element to be removed.
1446 * @param last Iterator pointing one past the last element to be removed.
1447 * @return An iterator pointing to the element pointed to by @a last
1448 * prior to erasing (or @c end()).
1449 *
1450 * If the container owns its elements, then the removed elements
1451 * will be deleted. Any duplicates will be removed in this process,
1452 * but don't rely on this.
1453 */
1454template <class T, class BASE>
1455typename DataVector<T, BASE>::iterator
1456DataVector<T, BASE>::erase(iterator first, iterator last)
1457{
1458 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1459 this->clearIndices (first, last);
1460 iterator ret (this->erase_base (first.base(), last.base()), this);
1461 this->shift (ret - this->begin() + (last-first), -(last-first));
1462 return ret;
1463}
1464
1465
1466/**
1467 * @brief Remove the last element from the collection.
1468 *
1469 * If the container owns its elements, then the removed element
1470 * will be deleted.
1471 */
1472template <class T, class BASE>
1473void DataVector<T, BASE>::pop_back()
1474{
1475 if (!this->m_pCont.empty()) {
1476 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1477 this->doDelete (this->m_pCont.back());
1478 else
1479 this->clearIndex (iterator (this->m_pCont.end() - 1, this));
1480 this->m_pCont.pop_back();
1481 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
1482 }
1483}
1484
1485
1486/**
1487 * @brief Erase all the elements in the collection.
1488 *
1489 * If the container owns its elements, then the removed elements
1490 * will be deleted. Any duplicates will be removed in this process,
1491 * but don't rely on this.
1492 */
1493template <class T, class BASE>
1494inline
1495void DataVector<T, BASE>::clear()
1496{
1497 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1498 this->clearIndices (begin(), end());
1499 this->erase_base (this->m_pCont.begin(), this->m_pCont.end());
1500 SG::AuxVectorBase::resize<DataVector> (0);
1501}
1502
1503
1504//=== Swap and sort.
1505
1506
1507/**
1508 * @brief Swap this collection with another.
1509 * @param rhs The collection with which to swap.
1510 *
1511 * Ownership is swapped along with the collection content.
1512 *
1513 * Note: this method may only be called using the most-derived
1514 * @c DataVector in the hierarchy. The @a rhs must also be
1515 * referenced using the most-derived @c DataVector.
1516 *
1517 * Warning: If this container has auxiliary data, then this
1518 * is an O(N) operation, not O(1).
1519 */
1520template <class T, class BASE>
1521void DataVector<T, BASE>::swap(DataVector& rhs)
1522{
1523 testInsert ("swap");
1524 rhs.testInsert ("swap");
1525 std::swap(this->m_ownPolicy, rhs.m_ownPolicy);
1526 SG::AuxVectorBase::swap (rhs);
1527 this->m_pCont.swap(rhs.m_pCont);
1528 std::swap (this->m_deleter, rhs.m_deleter);
1529 this->setIndices (this->begin(), this->end());
1530 rhs.setIndices (rhs.begin(), rhs.end());
1531}
1532
1533
1534/**
1535 * @brief Swap the referents of two @c DataVector iterators.
1536 * @param a The first iterator for the swap.
1537 * @param b The second iterator for the swap.
1538 */
1539template <class T, class BASE>
1540void DataVector<T, BASE>::iter_swap (iterator a, iterator b)
1541{
1542 if (a.ownPolicy() != b.ownPolicy()) {
1543 throw SG::ExcBadIterSwap();
1544 }
1545 a.testInsert ("iter_swap");
1546 b.testInsert ("iter_swap");
1547 std::iter_swap (a.base(), b.base());
1548 DataVector* acont = a.container();
1549 DataVector* bcont = b.container();
1550 if (typename SG::AuxStore_traits<DataVector>::flag())
1551 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
1552 b.base() - bcont->stdcont().begin(),
1553 DataModel_detail::DVLCast<DataVector>::cast(*a.base()),
1554 DataModel_detail::DVLCast<DataVector>::cast(*b.base()),
1555 bcont);
1556}
1557
1558
1559/**
1560 * @brief Sort the container.
1561 *
1562 * This just sorts by pointer value, so it's probably not very useful.
1563 */
1564template <class T, class BASE>
1565void DataVector<T, BASE>::sort()
1566{
1567 typedef std::less<typename PtrVector::value_type> less;
1568 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1569 DataModel_detail::Compwrapper<DataVector, less> (less()));
1570 this->resortAux (this->begin(), this->end());
1571}
1572
1573
1574/**
1575 * @brief Sort the container with a user-specified comparison operator.
1576 * @param comp Functional to compare two values.
1577 */
1578template <class T, class BASE>
1579template <class COMPARE>
1580void DataVector<T, BASE>::sort(COMPARE comp)
1581{
1582 std::sort (this->m_pCont.begin(), this->m_pCont.end(),
1583 DataModel_detail::Compwrapper<DataVector, COMPARE> (comp));
1584 this->resortAux (this->begin(), this->end());
1585}
1586
1587
1588//=== Non-standard operations.
1589
1590
1591/**
1592 * @brief Swap one element out of the container.
1593 * @param index Index of the element in the container to swap.
1594 * @param newElement New element to put in the container.
1595 * May be 0.
1596 * @param oldElem Reference to receive the element removed from the
1597 * container.
1598 *
1599 * Reference @a oldElem is initialized with element @a index of the
1600 * collection (no bounds checking). Then element @a index is set
1601 * to @newElem. If the collection owns its elements, then it will
1602 * take ownership of @a newElem and release (without deleting)
1603 * the element returned through @a oldElem.
1604 *
1605 * Note: this method may only be called using the most derived
1606 * @c DataVector in the hierarchy.
1607 */
1608template <class T, class BASE>
1609void DataVector<T, BASE>::swapElement(size_type index,
1610 value_type newElem,
1611 reference oldElem)
1612{
1613 testInsert ("swapElement");
1614 oldElem =
1615 DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]);
1616 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1617 this->m_pCont[index] = newElem;
1618 this->moveAux (index, newElem);
1619}
1620
1621
1622/**
1623 * @brief Swap one element out of the container.
1624 * @param pos The element in the container to swap.
1625 * @param newElem New element to put in the container.
1626 * May be 0.
1627 * @param oldElem Reference to receive the element removed from the
1628 * container.
1629 *
1630 * Reference @a oldElem is initialized with element @a pos of the
1631 * collection (no bounds checking). Then element @a index is set
1632 * to @c newElem. If the collection owns its elements, then it will
1633 * take ownership of @a newElem and release (without deleting)
1634 * the element returned through @a oldElem.
1635 *
1636 * Note: this method may only be called using the most derived
1637 * @c DataVector in the hierarchy.
1638 */
1639template <class T, class BASE>
1640void DataVector<T, BASE>::swapElement(iterator pos,
1641 value_type newElem,
1642 reference oldElem)
1643{
1644 testInsert ("swapElement");
1645 oldElem =
1646 DataModel_detail::DVLCast<DataVector>::cast(*pos.base());
1647 this->clearIndex (pos);
1648 *pos.base() = newElem;
1649 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
1650}
1651
1652
1653/**
1654 * @brief Swap one element out of the container.
1655 * @param index Index of the element in the container to swap.
1656 * @param newElement New element to put in the container.
1657 * May be 0.
1658 * @param oldElem Reference to receive the element removed from the
1659 * container.
1660 *
1661 * Reference @a oldElem is initialized with element @a index of the
1662 * collection (no bounds checking). Then element @a index is set
1663 * to @newElem.
1664 *
1665 * The collection must own its elements to use its interface.
1666 * The collection will take ownership of @c newElem and will return
1667 * ownership of @c oldElem.
1668 *
1669 * Note: this method may only be called using the most derived
1670 * @c DataVector in the hierarchy.
1671 */
1672template <class T, class BASE>
1673void DataVector<T, BASE>::swapElement(size_type index,
1674 std::unique_ptr<base_value_type> newElem,
1675 std::unique_ptr<base_value_type>& oldElem)
1676{
1677 // Container must own its elements.
1678 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1679 SG::throwExcNonowningContainer();
1680
1681 testInsert ("swapElement");
1682 oldElem = std::unique_ptr<base_value_type>
1683 (DataModel_detail::DVLCast<DataVector>::cast(this->m_pCont[index]));
1684 this->clearIndex (iterator (this->m_pCont.begin() + index, this));
1685 value_type ptr = newElem.release();
1686 this->m_pCont[index] = ptr;
1687 this->moveAux (index, ptr);
1688}
1689
1690
1691/**
1692 * @brief Swap one element out of the container.
1693 * @param pos The element in the container to swap.
1694 * @param newElem New element to put in the container.
1695 * May be 0.
1696 * @param oldElem Reference to receive the element removed from the
1697 * container.
1698 *
1699 * Reference @a oldElem is initialized with element @a pos of the
1700 * collection (no bounds checking). Then element @a index is set
1701 * to @c newElem.
1702 *
1703 * The collection must own its elements to use its interface.
1704 * The collection will take ownership of @c newElem and will return
1705 * ownership of @c oldElem.
1706 *
1707 * Note: this method may only be called using the most derived
1708 * @c DataVector in the hierarchy.
1709 */
1710template <class T, class BASE>
1711void DataVector<T, BASE>::swapElement(iterator pos,
1712 std::unique_ptr<base_value_type> newElem,
1713 std::unique_ptr<base_value_type>& oldElem)
1714{
1715 // Container must own its elements.
1716 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1717 SG::throwExcNonowningContainer();
1718
1719 testInsert ("swapElement");
1720 oldElem = std::unique_ptr<base_value_type>
1721 (DataModel_detail::DVLCast<DataVector>::cast(*pos.base()));
1722 this->clearIndex (pos);
1723 value_type ptr = newElem.release();
1724 *pos.base() = ptr;
1725 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
1726}
1727
1728
1729/**
1730 * @brief Erase all the elements in the collection, and reset
1731 * the ownership mode.
1732 * @param ownPolicy The new ownership policy of the container.
1733 *
1734 * If the container owns its elements, then the removed elements
1735 * will be deleted. Any duplicates will be removed in this process,
1736 * but don't rely on this.
1737 */
1738template <class T, class BASE>
1739void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy)
1740{
1741 this->clear();
1742 this->m_ownPolicy = ownPolicy;
1743 this->template initAuxVectorBase<DataVector> (ownPolicy,
1744 SG::DEFAULT_TRACK_INDICES);
1745}
1746
1747
1748/**
1749 * @brief Erase all the elements in the collection, and reset
1750 * the ownership mode.
1751 * @param ownPolicy The new ownership policy of the container.
1752 * @param trackIndices The index tracking policy.
1753 *
1754 * If the container owns its elements, then the removed elements
1755 * will be deleted. Any duplicates will be removed in this process,
1756 * but don't rely on this.
1757 */
1758template <class T, class BASE>
1759void DataVector<T, BASE>::clear (SG::OwnershipPolicy ownPolicy,
1760 SG::IndexTrackingPolicy trackIndices)
1761{
1762 this->clear();
1763 this->m_ownPolicy = ownPolicy;
1764 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
1765}
1766
1767
1768/**
1769 * @brief Return the DV/DL info struct for this class.
1770 *
1771 * This can be used to make sure that it's instantiated.
1772 */
1773template <class T, class BASE>
1774const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo()
1775{
1776 static const DataModel_detail::DVLInfo<DataVector<T, BASE> > info;
1777 return info;
1778}
1779
1780
1781/**
1782 * @brief Erase all the elements in the collection, and change
1783 * how elements are to be deleted.
1784 * @param deleter Object to be used to delete object.
1785 * Passing nullptr will change back to the default.
1786 *
1787 * If the container owns its elements, then the removed elements
1788 * will be deleted. Any duplicates will be removed in this process,
1789 * but don't rely on this.
1790 * After the current elements are deleted, the Deleter object is changed.
1791 */
1792template <class T, class BASE>
1793void DataVector<T, BASE>::clear (std::unique_ptr<Deleter> deleter)
1794{
1795 this->clear();
1796 delete this->m_deleter;
1797 this->m_deleter = deleter.release();
1798}
1799
1800
1801/**
1802 * @brief Return the DV/DL info struct for this class.
1803 *
1804 * This can be used to make sure that it's instantiated.
1805 */
1806template <class T, class BASE>
1807const DataModel_detail::DVLInfoBase& DataVector<T, BASE>::dvlinfo_v() const
1808{
1809 return DataVector<T, BASE>::dvlinfo();
1810}
1811
1812
1813/**
1814 * @brief Return the offset of a base @c DataVector class.
1815 * @param ti @c std::type_info of the desired class.
1816 *
1817 * If @c ti represents a @c DataVector base class of this one,
1818 * then return the offset of that base class. Otherwise, return -1.
1819 *
1820 * This function is here due to limitations of root 6, which can't
1821 * calculate these offsets correctly from the dictionary if
1822 * virtual derivation is used.
1823 */
1824template <class T, class BASE>
1825int DataVector<T, BASE>::baseOffset (const std::type_info& ti)
1826{
1827 DataVector dv;
1828 return baseOffset1 (reinterpret_cast<const char*>(&dv), dv, ti);
1829}
1830
1831
1832/**
1833 * @brief Convert to @c AuxVectorBase.
1834 *
1835 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
1836 * Present in @c DataVector as well for consistency.
1837 * We only really need it in the base class; however, root6 fails
1838 * constructing a @c TMethodCall for this if there is virtual
1839 * derivation. A workaround is to redeclare this in the derived
1840 * classes too.
1841 */
1842template <class T, class BASE>
1843const SG::AuxVectorBase& DataVector<T, BASE>::auxbase() const
1844{
1845 return *this;
1846}
1847
1848
1849//=== Internal operations.
1850
1851
1852/**
1853 * @brief Helper for @c baseOffset.
1854 * @param p Pointer to the start of the top-level object.
1855 * @param dv Reference to the DataVector object.
1856 * @param ti @c std::type_info of the desired class.
1857 *
1858 * If @c ti represents a @c DataVector base class of this one,
1859 * then return the offset of that base class. Otherwise, return -1.
1860 *
1861 */
1862template <class T, class BASE>
1863int DataVector<T, BASE>::baseOffset1 (const char* p, const DataVector& dv,
1864 const std::type_info& ti)
1865{
1866 if (typeid(DataVector) == ti)
1867 return reinterpret_cast<const char*>(&dv) - p;
1868 return BASE::baseOffset1 (p, dv, ti);
1869}
1870
1871
1872/**
1873 * @brief Reset indices / reorder aux data after elements have been permuted.
1874 * @param beg Start of the range of elements to process.
1875 * @param end End of the range of elements to process.
1876 *
1877 * Call this after some operation that has permuted the elements in the
1878 * container (such as sort). The index information in the elements
1879 * will be used to permute all auxiliary data in the same way.
1880 * Finally, all the indices will be reset in the correct order.
1881 */
1882template <class T, class BASE>
1883void DataVector<T, BASE>::resortAux (iterator beg, iterator end)
1884{
1885 if (typename SG::AuxStore_traits<DataVector>::flag() &&
1886 beg >= this->begin() && end <= this->end())
1887 {
1888 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
1889 }
1890}
1891
1892
1893/**
1894 * @brief Test if we can insert; raise an exception if not.
1895 * @param op Description of the attempted operation.
1896 *
1897 * In order to maintain type-safety, we can only allow insertions
1898 * using the most-derived instance of @c DataVector. This checks
1899 * this by testing the @c m_isMostDerived, which is set by the constructors
1900 * to true only for the most-derived instance.
1901 * If the test fails, we call to potentially out-of-line code to continue.
1902 */
1903template <class T, class BASE>
1904inline
1905void DataVector<T, BASE>::testInsert (const char* op)
1906{
1907 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
1908 return;
1909 this->testInsertOol (op);
1910}
1911
1912
1913/**
1914 * @brief Test if we can insert; raise an exception if not.
1915 * @param op Description of the attempted operation.
1916 *
1917 * This continues the test of @c testInsert. There is one case
1918 * where @c m_isMostDerived may not be set correctly. If this container
1919 * was made via copy construction, then all the @c m_isMostDerived flags
1920 * will be false. So we call @c setMostDerived to set the flags correctly
1921 * and test again. If the test fails again, then we raise an exception.
1922 */
1923template <class T, class BASE>
1924void DataVector<T, BASE>::testInsertOol (const char* op)
1925{
1926 this->setMostDerived();
1927 if (!m_isMostDerived)
1928 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
1929}
1930
1931
1932/**
1933 * @brief Handle element assignment.
1934 * @param pos Position in the container to assign.
1935 * @param newElem The new element to assign.
1936 *
1937 * The old element is freed if this container owns elements.
1938 * Auxiliary data are copied if appropriate.
1939 */
1940template <class T, class BASE>
1941void DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1942 value_type newElem)
1943{
1944 testInsert ("assignElement");
1945 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1946 this->doDelete (*pos);
1947 else
1948 this->clearIndex (iterator (pos, this));
1949 *pos = newElem;
1950 this->moveAux (pos - this->m_pCont.begin(), newElem);
1951}
1952
1953
1954/**
1955 * @brief Handle element assignment.
1956 * @param pos Position in the container to assign.
1957 * @param newElem The new element to assign.
1958 *
1959 * The container must own its elements.
1960 * Auxiliary data are copied if appropriate.
1961 */
1962template <class T, class BASE>
1963void
1964DataVector<T, BASE>::assignElement (typename BaseContainer::iterator pos,
1965 std::unique_ptr<base_value_type> newElem)
1966{
1967 // Container must own its elements.
1968 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
1969 SG::throwExcNonowningContainer();
1970
1971 testInsert ("assignElement");
1972 this->doDelete (*pos);
1973 value_type ptr = newElem.release();
1974 *pos = ptr;
1975 this->moveAux (pos - this->m_pCont.begin(), ptr);
1976}
1977
1978
1979/**
1980 * @brief Handle element assignment from a base pointer.
1981 * @param pos Position in the container to assign.
1982 * @param newElem The new element to assign.
1983 *
1984 * The old element is freed if this container owns elements.
1985 * Auxiliary data are copied if appropriate.
1986 */
1987template <class T, class BASE>
1988void
1989DataVector<T, BASE>::assignBaseElement (typename BaseContainer::iterator pos,
1990 typename BaseContainer::value_type newElem)
1991{
1992 testInsert ("assignBaseElement");
1993 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
1994 this->doDelete (*pos);
1995 else
1996 this->clearIndex (iterator (pos, this));
1997 *pos = newElem;
1998 if (typename SG::AuxStore_traits<DataVector>::flag())
1999 this->moveAux (pos - this->m_pCont.begin(),
2000 DataModel_detail::DVLCast<DataVector>::cast(newElem));
2001}
2002
2003
2004/**
2005 * @brief Shift the auxiliary elements of the container.
2006 * @param pos The starting index for the shift.
2007 * @param offs The (signed) amount of the shift.
2008 *
2009 * The elements in the container should have already been shifted;
2010 * this operation will then adjust the element indices and also shift
2011 * the elements in the vectors for all aux data items.
2012 * @c offs may be either positive or negative.
2013 *
2014 * If @c offs is positive, then the container is growing.
2015 * The container size should be increased by @c offs,
2016 * the element at @c pos moved to @c pos + @c offs,
2017 * and similarly for following elements.
2018 * The elements between @c pos and @c pos + @c offs should
2019 * be default-initialized.
2020 *
2021 * If @c offs is negative, then the container is shrinking.
2022 * The element at @c pos should be moved to @c pos + @c offs,
2023 * and similarly for following elements.
2024 * The container should then be shrunk by @c -offs elements
2025 * (running destructors as appropriate).
2026 */
2027template <class T, class BASE>
2028void DataVector<T, BASE>::shift (size_t pos, ptrdiff_t offs)
2029{
2030 SG::AuxVectorBase::shift (*this, pos, offs);
2031}
2032
2033
2034/**
2035 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
2036 * @param p The value to convert.
2037 * @return The value as a @c const @c T*.
2038 *
2039 * The conversion will be done with @c static_cast if possible,
2040 * with @c dynamic_cast otherwise.
2041 */
2042template <class T, class BASE>
2043inline
2044const T*
2045DataVector<T, BASE>::do_cast (const typename PtrVector::value_type p)
2046{
2047 return DataModel_detail::DVLCast<DataVector>::cast (p);
2048}
2049
2050
2051/**
2052 * @brief Helper to shorten calls to @c DataVector_detail::DVLCast.
2053 * @param p The value to convert.
2054 * @return The value as a @c T*.
2055 *
2056 * The conversion will be done with @c static_cast if possible,
2057 * with @c dynamic_cast otherwise.
2058 */
2059template <class T, class BASE>
2060inline
2061T*
2062DataVector<T, BASE>::do_cast_nc (typename PtrVector::value_type p)
2063{
2064 return DataModel_detail::DVLCast<DataVector>::cast (p);
2065}
2066
2067
2068/**
2069 * @brief Find the most-derived @c DataVector class in the hierarchy.
2070 * @return The @c type_info for the class for which this method gets run.
2071 *
2072 * This is used to generate a nice error message when the most-derived
2073 * check for insertions fails.
2074 * Every @c DataVector defines this virtual method, so when it's
2075 * called, the one corresponding to the most-derived @c DataVector
2076 * gets run.
2077 */
2078template <class T, class BASE>
2079const std::type_info& DataVector<T, BASE>::dv_typeid() const
2080{
2081 return typeid(DataVector);
2082}
2083
2084
2085/**
2086 * @brief Clear @c m_isMostDerived for this instance and for all bases.
2087 *
2088 * Called from the constructor after setting @c m_isMostDerived.
2089 */
2090template <class T, class BASE>
2091inline
2092void DataVector<T, BASE>::clearMostDerived()
2093{
2094 this->m_isMostDerived = false;
2095 BASE::clearMostDerived();
2096}
2097
2098
2099/**
2100 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
2101 *
2102 * Called from @c testInsert if the test fails. The flag may not have
2103 * been set if this container was made via copy construction, so set
2104 * it appropriately now so we can test again.
2105 */
2106template <class T, class BASE>
2107void DataVector<T, BASE>::setMostDerived()
2108{
2109 m_isMostDerived = true;
2110 BASE::clearMostDerived();
2111}
2112
2113
2114//****************************************************************************
2115// Specialized (base) DataVector implementation.
2116//
2117
2118
2119// An abbreviation for the DataVector specialization to try to make
2120// things a little more readable.
2121#define DATAVECTOR DataVector<T, DataModel_detail::NoBase>
2122
2123
2124//=== Constructors, destructors, assignment.
2125
2126/**
2127 * @brief Default constructor.
2128 * @param ownPolicy The ownership mode for the container.
2129 * @param trackIndices The index tracking policy.
2130 *
2131 * By default, a @c DataVector will own its elements.
2132 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2133 */
2134template <class T>
2135inline
2136DATAVECTOR::DataVector
2137 (SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2138 SG::IndexTrackingPolicy trackIndices /*=SG::DEFAULT_TRACK_INDICES*/)
2139 : m_ownPolicy(ownPolicy)
2140{
2141 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2142 this->m_isMostDerived = true;
2143}
2144
2145
2146/**
2147 * @brief Sized constructor.
2148 * @param n The size of the container.
2149 * @param ownPolicy The ownership mode for the container.
2150 * @param trackIndices The index tracking policy.
2151 *
2152 * Note that unlike the standard vector constructor, you can't specify
2153 * an initial value here. The container will be initialized with 0's.
2154 *
2155 * By default, a @c DataVector will own its elements.
2156 * To avoid this, pass @c SG::VIEW_ELEMENTS for @a ownPolicy.
2157 */
2158template <class T>
2159inline
2160DATAVECTOR::DataVector
2161 (size_type n,
2162 SG::OwnershipPolicy ownPolicy /*= SG::OWN_ELEMENTS*/,
2163 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/)
2164 : m_ownPolicy(ownPolicy),
2165 m_pCont (n)
2166{
2167 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2168 this->m_isMostDerived = true;
2169}
2170
2171
2172/**
2173 * @brief Copy constructor.
2174 * @param rhs The container from which to copy.
2175 *
2176 * This is a `shallow' copy; the new container will not own its elements.
2177 */
2178template <class T>
2179inline
2180DATAVECTOR::DataVector(const DataVector& rhs)
2181 : AuxVectorBase(),
2182 m_ownPolicy(SG::VIEW_ELEMENTS),
2183 m_pCont(rhs.m_pCont)
2184{
2185 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2186 SG::DEFAULT_TRACK_INDICES);
2187 // Leave m_isMostDerived false here, because we may be being called
2188 // from a derived class implicit copy constructor. The flags will get
2189 // set correctly when @c testInsert gets called.
2190}
2191
2192
2193/**
2194 * @brief Move constructor.
2195 * @param rhs The container from which to move.
2196 *
2197 * Any auxiliary data will be moved along with the container contents.
2198 */
2199template <class T>
2200inline
2201DATAVECTOR::DataVector(DataVector&& rhs) noexcept
2202 : AuxVectorBase (std::move (rhs)),
2203 m_ownPolicy(rhs.m_ownPolicy),
2204 m_pCont(std::move (rhs.m_pCont))
2205{
2206 m_deleter = std::move(rhs.m_deleter);
2207 rhs.m_deleter = nullptr;
2208
2209 // Need to reset the container pointer on elements.
2210 // Functions called from here can throw GaudiException.
2211 // However, logically that should not actually happen; so leave this
2212 // declared as noexcept.
2213 this->setIndices (this->begin(), this->end());
2214
2215 // This doesn't get called from derived classes.
2216 // Go ahead and set this flag now.
2217 m_isMostDerived = true;
2218}
2219
2220
2221/**
2222 * @brief Constructor from iterators.
2223 * @param first The start of the range to put in the new container.
2224 * @param last The end of the range to put in the new container.
2225 * @param ownPolicy The ownership mode for the container.
2226 * @param trackIndices The index tracking policy.
2227 * @param store An associated auxiliary data store.
2228 *
2229 * By default, a view container is made, which does not own its elements.
2230 * To have the container take ownership of the pointers passed
2231 * to this constructor, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2232 */
2233template <class T>
2234template <class InputIterator>
2235inline
2236DATAVECTOR::DataVector
2237 (InputIterator first,
2238 InputIterator last,
2239 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2240 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2241 SG::IAuxStore* store /*= 0*/)
2242 : m_ownPolicy(ownPolicy)
2243{
2244 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
2245 this->m_isMostDerived = true;
2246 if (store)
2247 this->setStore (store);
2248 insert (this->begin(), first, last);
2249}
2250
2251
2252/**
2253 * @brief Constructor from an initializer list.
2254 * @param l An initializer list.
2255 * @param last The end of the range to put in the new container.
2256 * @param ownPolicy The ownership mode for the container.
2257 * @param trackIndices The index tracking policy.
2258 * @param store An associated auxiliary data store.
2259 *
2260 *
2261 * A @c DataVector constructed this way will *not* own its elements
2262 * by default. To change this, pass @c SG::OWN_ELEMENTS for @a ownPolicy.
2263 */
2264template <class T>
2265inline
2266DATAVECTOR::DataVector
2267 (std::initializer_list<value_type> l,
2268 SG::OwnershipPolicy ownPolicy /*= SG::VIEW_ELEMENTS*/,
2269 SG::IndexTrackingPolicy trackIndices /*= SG::DEFAULT_TRACK_INDICES*/,
2270 SG::IAuxStore* store /*= 0*/)
2271 : DataVector (l.begin(), l.end(), ownPolicy, trackIndices, store)
2272{
2273}
2274
2275
2276/**
2277 * @brief Assignment operator.
2278 * @param rhs The DataVector from which to assign.
2279 * @return This object.
2280 *
2281 * This is a `shallow' copy; after the completion of this, the @c DataVector
2282 * will not own its elements. Any elements it owned prior to this call
2283 * will be released.
2284 *
2285 * Note: this method may only be called using the most derived
2286 * @c DataVector in the hierarchy.
2287 */
2288template <class T>
2289inline
2290DATAVECTOR& DATAVECTOR::operator= (const DataVector& rhs)
2291{
2292 if (&rhs != this) {
2293 // Ensure we're not being called via a base class.
2294 // This can throw an exception, so this method should not be noexcept.
2295 testInsert ("assignment operator");
2296 clear(); // Release any currently-owned elements.
2297 m_ownPolicy = SG::VIEW_ELEMENTS;
2298 this->setStore ((SG::IConstAuxStore*)0);
2299 this->template initAuxVectorBase<DataVector> (m_ownPolicy,
2300 SG::DEFAULT_TRACK_INDICES);
2301 m_pCont = rhs.m_pCont;
2302 }
2303 return *this;
2304}
2305
2306
2307/**
2308 * @brief Move assignment.
2309 * @param rhs The container from which to move.
2310 *
2311 * Any auxiliary data will be moved along with the container contents.
2312 */
2313template <class T>
2314DATAVECTOR& DATAVECTOR::operator= (DATAVECTOR&& rhs)
2315{
2316 if (this != &rhs) {
2317 // Ensure we're not being called via a base class.
2318 // This can throw an exception, so this method should not be noexcept.
2319 testInsert ("assignment operator");
2320
2321 this->clear(); // Release any currently-owned elements.
2322
2323 SG::AuxVectorBase::operator= (std::move (rhs));
2324 this->m_ownPolicy = rhs.m_ownPolicy;
2325 this->m_pCont = std::move (rhs.m_pCont);
2326
2327 delete this->m_deleter;
2328 this->m_deleter = std::move(rhs.m_deleter);
2329 rhs.m_deleter = nullptr;
2330
2331 // Need to reset the container pointer on elements.
2332 this->setIndices (this->begin(), this->end());
2333 }
2334 return *this;
2335}
2336
2337
2338/**
2339 * @brief Assignment operator, from an initializer list.
2340 * @param l An initializer list.
2341 * @return This object.
2342 *
2343 * This is equivalent to @c assign.
2344 * Any existing owned elements will be released.
2345 * The @c DataVector's ownership policy determines whether it will take
2346 * ownership of the new elements.
2347 */
2348template <class T>
2349inline
2350DATAVECTOR& DATAVECTOR::operator= (std::initializer_list<value_type> l)
2351{
2352 this->assign (l.begin(), l.end());
2353 return *this;
2354}
2355
2356
2357/**
2358 * @brief Assign from iterators.
2359 * @param first The start of the range to put in the container.
2360 * @param last The end of the range to put in the container.
2361 *
2362 * Any existing owned elements will be released.
2363 * The @c DataVector's ownership policy determines whether it will take
2364 * ownership of the new elements.
2365 */
2366template <class T>
2367template <class InputIterator>
2368void DATAVECTOR::assign (InputIterator first,
2369 InputIterator last)
2370{
2371 // Ensure we're not being called via a base class.
2372 testInsert ("assign");
2373 clear(); // Release any currently-owned elements.
2374 insert(begin(), first, last);
2375}
2376
2377
2378/**
2379 * @brief Assign from an initializer list.
2380 * @param l An initializer list.
2381 *
2382 * Any existing owned elements will be released.
2383 * The @c DataVector's ownership policy determines whether it will take
2384 * ownership of the new elements.
2385 */
2386template <class T>
2387void DATAVECTOR::assign (std::initializer_list<value_type> l)
2388{
2389 this->assign (l.begin(), l.end());
2390}
2391
2392
2393/**
2394 * @brief Destructor.
2395 *
2396 * If this container owns its elements, the contained elements will
2397 * be deleted as well. Before doing this, the destructor will scan
2398 * for duplicate pointers (takes @f$n \log n@f$ time); duplicates are only
2399 * destroyed once. Duplicates should, however, be considered an error;
2400 * don't rely on this behavior.
2401 */
2402template <class T>
2403DATAVECTOR::~DataVector()
2404{
2405 if (m_ownPolicy == SG::OWN_ELEMENTS) {
2406 typename PtrVector::iterator new_end =
2407 DataVector_detail::remove_duplicates(m_pCont.begin(), m_pCont.end());
2408 this->doDelete (m_pCont.begin(), new_end);
2409 }
2410 delete m_deleter;
2411}
2412
2413
2414//=== Size and capacity.
2415
2416
2417/**
2418 * @brief Returns the number of elements in the collection.
2419 */
2420template <class T>
2421inline
2422typename DATAVECTOR::size_type DATAVECTOR::size() const noexcept
2423{
2424 return m_pCont.size();
2425}
2426
2427
2428/**
2429 * @brief Returns the number of elements in the collection.
2430 *
2431 * This version is virtual, to be callable from the AuxData
2432 * base class.
2433 */
2434template <class T>
2435inline
2436typename DATAVECTOR::size_type DATAVECTOR::size_v() const
2437{
2438 return this->size();
2439}
2440
2441
2442/**
2443 * @brief Returns the @c size() of the largest possible collection.
2444 */
2445template <class T>
2446inline
2447typename DATAVECTOR::size_type DATAVECTOR::max_size() const noexcept
2448{
2449 return m_pCont.max_size();
2450}
2451
2452
2453/**
2454 * @brief Resizes the collection to the specified number of elements.
2455 * @param sz The new size of the collection.
2456 *
2457 * Note that this function differs from the standard in that it does
2458 * not allow specifying the value of any inserted elements.
2459 * They will always be 0.
2460 *
2461 * If the container is shrunk, elements will be deleted as with @c erase().
2462 */
2463template <class T>
2464void DATAVECTOR::resize(size_type sz)
2465{
2466 if (sz < this->size()) {
2467 this->erase (this->begin()+sz, this->end());
2468 } else {
2469 this->m_pCont.insert(this->m_pCont.end(), sz - this->m_pCont.size(), 0);
2470 SG::AuxVectorBase::resize<DataVector> (sz);
2471 }
2472}
2473
2474
2475/**
2476 * @brief Returns the total number of elements that the collection can hold
2477 * before needing to allocate more memory.
2478 */
2479template <class T>
2480inline
2481typename DATAVECTOR::size_type DATAVECTOR::capacity() const noexcept
2482{
2483 return m_pCont.capacity();
2484}
2485
2486
2487/**
2488 * @brief Returns the total number of elements that the collection can hold
2489 * before needing to allocate more memory.
2490 *
2491 * This version is virtual, to be callable from the AuxData
2492 * base class.
2493 */
2494template <class T>
2495inline
2496typename DATAVECTOR::size_type DATAVECTOR::capacity_v() const
2497{
2498 return capacity();
2499}
2500
2501
2502/**
2503 * @brief Returns @c true if the collection is empty.
2504 */
2505template <class T>
2506inline
2507bool DATAVECTOR::empty() const noexcept
2508{
2509 return m_pCont.empty();
2510}
2511
2512
2513/**
2514 * @brief Attempt to preallocate enough memory for a specified number
2515 * of elements.
2516 * @param n Number of elements required.
2517 */
2518template <class T>
2519inline
2520void DATAVECTOR::reserve (size_type n)
2521{
2522 m_pCont.reserve (n);
2523 SG::AuxVectorBase::reserve<DataVector> (n);
2524}
2525
2526
2527/**
2528 * @brief Change the vector capacity to match the current size.
2529 *
2530 * Note: this does not affect auxiliary data.
2531 */
2532template <class T>
2533inline
2534void DATAVECTOR::shrink_to_fit()
2535{
2536 m_pCont.shrink_to_fit();
2537}
2538
2539
2540//=== Element access.
2541
2542
2543/**
2544 * @brief Access an element, as an rvalue.
2545 * @param n Array index to access.
2546 * @return The element at @a n.
2547 *
2548 * No bounds checking is done.
2549 * Note that we return a @c const @c T* rather than a reference.
2550 */
2551template <class T>
2552inline
2553const T* DATAVECTOR::operator[] (size_type n) const
2554{
2555 return m_pCont[n];
2556}
2557
2558
2559/**
2560 * @brief Access an element, as an rvalue.
2561 * @param n Array index to access.
2562 * @return The element at @a n.
2563 *
2564 * This is a synonym for operator[] const, to be used when calling from root
2565 * (where we can't readily call just the const version of a method).
2566 */
2567template <class T>
2568inline
2569const T* DATAVECTOR::get (size_type n) const
2570{
2571 return do_cast(this->m_pCont[n]);
2572}
2573
2574
2575/**
2576 * @brief Access an element, as an lvalue.
2577 * @param n Array index to access.
2578 * @return Proxy to the element at @a n.
2579 *
2580 * No bounds checking is done.
2581 * Note that we return a proxy object rather than a reference;
2582 * the proxy will handle deleting an owned element if it's assigned to.
2583 */
2584template <class T>
2585inline
2586typename DATAVECTOR::ElementProxy DATAVECTOR::operator[] (size_type n)
2587{
2588 return ElementProxy (m_pCont.begin() + n, this);
2589}
2590
2591
2592/**
2593 * @brief Access an element, as an rvalue.
2594 * @param n Array index to access.
2595 * @return The element at @a n.
2596 *
2597 * Will raise @c std::out_of_range if the index is out-of-bounds.
2598 * Note that we return a @c const @c T* rather than a reference.
2599 */
2600template <class T>
2601inline
2602const T* DATAVECTOR::at (size_type n) const
2603{
2604 return m_pCont.at(n);
2605}
2606
2607
2608/**
2609 * @brief Access an element, as an lvalue.
2610 * @param n Array index to access.
2611 * @return Proxy to the element at @a n.
2612 *
2613 * Will raise @c std::out_of_range if the index is out-of-bounds.
2614 * Note that we return a proxy object rather than a reference;
2615 * the proxy will handle deleting an owned element if it's assigned to.
2616 */
2617template <class T>
2618inline
2619typename DATAVECTOR::ElementProxy DATAVECTOR::at (size_type n)
2620{
2621 // Can't use m_pCont's at here, because we need an iterator.
2622 // So we have to do the bounds check ourselves.
2623 if (n >= size())
2624 CxxUtils::throw_out_of_range (__PRETTY_FUNCTION__, n, this->size(), this);
2625 return ElementProxy (m_pCont.begin() + n, this);
2626}
2627
2628
2629/**
2630 * @brief Access the first element in the collection as an rvalue.
2631 * @return The first element in the collection.
2632 *
2633 * No checking is done to ensure that the container is not empty.
2634 * Note that we return a @c const @c T* rather than a reference.
2635 */
2636template <class T>
2637inline
2638const T* DATAVECTOR::front() const
2639{
2640 return m_pCont.front();
2641}
2642
2643
2644/**
2645 * @brief Access the last element in the collection as an rvalue.
2646 * @return The last element in the collection.
2647 *
2648 * No checking is done to ensure that the container is not empty.
2649 * Note that we return a @c const @c T* rather than a reference.
2650 */
2651template <class T>
2652inline
2653const T* DATAVECTOR::back() const
2654{
2655 return m_pCont.back();
2656}
2657
2658
2659/**
2660 * @brief Access the first element in the collection as an lvalue.
2661 * @return Proxy to the first element in the collection.
2662 *
2663 * No checking is done to ensure that the container is not empty.
2664 * Note that we return a proxy object rather than a reference;
2665 * the proxy will handle deleting an owned element if it's assigned to.
2666 */
2667template <class T>
2668inline
2669typename DATAVECTOR::ElementProxy DATAVECTOR::front ()
2670{
2671 return ElementProxy (m_pCont.begin(), this);
2672}
2673
2674
2675/**
2676 * @brief Access the last element in the collection as an lvalue.
2677 * @return Proxy to the last element in the collection.
2678 *
2679 * No checking is done to ensure that the container is not empty.
2680 * Note that we return a proxy object rather than a reference;
2681 * the proxy will handle deleting an owned element if it's assigned to.
2682 */
2683template <class T>
2684inline
2685typename DATAVECTOR::ElementProxy DATAVECTOR::back ()
2686{
2687 return ElementProxy (m_pCont.end()-1, this);
2688}
2689
2690
2691//=== Iterator creation.
2692
2693
2694/**
2695 * @brief Return a @c const_iterator pointing at the beginning
2696 * of the collection.
2697 * @return A @c const_iterator.
2698 *
2699 * Note that dereferencing the iterator will yield a @c const @c T* rather
2700 * than a reference.
2701 */
2702template <class T>
2703inline
2704typename DATAVECTOR::const_iterator DATAVECTOR::begin() const noexcept
2705{
2706 return m_pCont.begin();
2707}
2708
2709
2710/**
2711 * @brief Return a @c const_iterator pointing past the end
2712 * of the collection.
2713 * @return A @c const_iterator.
2714 *
2715 * Note that dereferencing the iterator will yield a @c const @c T* rather
2716 * than a reference.
2717 */
2718template <class T>
2719inline
2720typename DATAVECTOR::const_iterator DATAVECTOR::end() const noexcept
2721{
2722 return m_pCont.end();
2723}
2724
2725
2726/**
2727 * @brief Return an @c iterator pointing at the beginning
2728 * of the collection.
2729 * @return An @c iterator.
2730 *
2731 * Note that dereferencing the iterator will yield a proxy rather
2732 * than a reference; the proxy will handle deleting an owned element
2733 * if it's assigned to.
2734 */
2735template <class T>
2736inline
2737typename DATAVECTOR::iterator DATAVECTOR::begin() noexcept
2738{
2739 return iterator (m_pCont.begin(), this);
2740}
2741
2742
2743/**
2744 * @brief Return an @c iterator pointing past the end
2745 * of the collection.
2746 * @return An @c iterator.
2747 *
2748 * Note that dereferencing the iterator will yield a proxy rather
2749 * than a reference; the proxy will handle deleting an owned element
2750 * if it's assigned to.
2751 */
2752template <class T>
2753inline
2754typename DATAVECTOR::iterator DATAVECTOR::end() noexcept
2755{
2756 return iterator (m_pCont.end(), this);
2757}
2758
2759
2760/**
2761 * @brief Return a @c const_reverse_iterator pointing past the end
2762 * of the collection.
2763 * @return A @c const_reverse_iterator.
2764 *
2765 * Note that dereferencing the iterator will yield a @c const @c T* rather
2766 * than a reference.
2767 */
2768template <class T>
2769inline
2770typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rbegin() const noexcept
2771{
2772 return const_reverse_iterator (m_pCont.end());
2773}
2774
2775
2776/**
2777 * @brief Return a @c const_reverse_iterator pointing at the beginning
2778 * of the collection.
2779 * @return A @c const_reverse_iterator.
2780 *
2781 * Note that dereferencing the iterator will yield a @c const @c T* rather
2782 * than a reference.
2783 */
2784template <class T>
2785inline
2786typename DATAVECTOR::const_reverse_iterator DATAVECTOR::rend() const noexcept
2787{
2788 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2789}
2790
2791
2792/**
2793 * @brief Return a @c reverse_iterator pointing past the end
2794 * of the collection.
2795 * @return A @c reverse_iterator.
2796 *
2797 * Note that dereferencing the iterator will yield a proxy rather
2798 * than a reference; the proxy will handle deleting an owned element
2799 * if it's assigned to.
2800 */
2801template <class T>
2802inline
2803typename DATAVECTOR::reverse_iterator DATAVECTOR::rbegin() noexcept
2804{
2805 return reverse_iterator(iterator (m_pCont.end(), this));
2806}
2807
2808
2809/**
2810 * @brief Return a @c reverse_iterator pointing at the beginning
2811 * of the collection.
2812 * @return A @c reverse_iterator.
2813 *
2814 * Note that dereferencing the iterator will yield a proxy rather
2815 * than a reference; the proxy will handle deleting an owned element
2816 * if it's assigned to.
2817 */
2818template <class T>
2819inline
2820typename DATAVECTOR::reverse_iterator DATAVECTOR::rend() noexcept
2821{
2822 return reverse_iterator(iterator (m_pCont.begin(), this));
2823}
2824
2825
2826/**
2827 * @brief Return a @c const_iterator pointing at the beginning
2828 * of the collection.
2829 * @return A @c const_iterator.
2830 *
2831 * Note that dereferencing the iterator will yield a @c const @c T* rather
2832 * than a reference.
2833 */
2834template <class T>
2835inline
2836typename DATAVECTOR::const_iterator DATAVECTOR::cbegin() const noexcept
2837{
2838 return m_pCont.begin();
2839}
2840
2841
2842/**
2843 * @brief Return a @c const_iterator pointing past the end
2844 * of the collection.
2845 * @return A @c const_iterator.
2846 *
2847 * Note that dereferencing the iterator will yield a @c const @c T* rather
2848 * than a reference.
2849 */
2850template <class T>
2851inline
2852typename DATAVECTOR::const_iterator DATAVECTOR::cend() const noexcept
2853{
2854 return m_pCont.end();
2855}
2856
2857
2858/**
2859 * @brief Return a @c const_reverse_iterator pointing past the end
2860 * of the collection.
2861 * @return A @c const_reverse_iterator.
2862 *
2863 * Note that dereferencing the iterator will yield a @c const @c T* rather
2864 * than a reference.
2865 */
2866template <class T>
2867inline
2868typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crbegin() const noexcept
2869{
2870 return const_reverse_iterator (m_pCont.end());
2871}
2872
2873
2874/**
2875 * @brief Return a @c const_reverse_iterator pointing at the beginning
2876 * of the collection.
2877 * @return A @c const_reverse_iterator.
2878 *
2879 * Note that dereferencing the iterator will yield a @c const @c T* rather
2880 * than a reference.
2881 */
2882template <class T>
2883inline
2884typename DATAVECTOR::const_reverse_iterator DATAVECTOR::crend() const noexcept
2885{
2886 return const_reverse_iterator (const_iterator (m_pCont.begin()));
2887}
2888
2889
2890//=== Insertion operations.
2891
2892
2893/**
2894 * @brief Add an element to the end of the collection.
2895 * @param pElem The element to add to the collection.
2896 *
2897 * The container's ownership policy will determine if it takes ownership
2898 * of the new element.
2899 *
2900 * Note: this method may only be called using the most derived
2901 * @c DataVector in the hierarchy.
2902 *
2903 * Returns the pushed pointer.
2904 */
2905template <class T>
2906inline
2907typename DATAVECTOR::value_type
2908DATAVECTOR::push_back(value_type pElem)
2909{
2910 // Ensure we're not being called via a base class.
2911 testInsert ("push_back");
2912 m_pCont.push_back(pElem);
2913 SG::AuxVectorBase::resize<DataVector> (this->size());
2914 if (pElem && this->trackIndices())
2915 this->moveAuxNoClear (this->size()-1, pElem);
2916 return pElem;
2917}
2918
2919
2920/**
2921 * @brief Add an element to the end of the collection.
2922 * @param pElem The element to add to the collection.
2923 *
2924 * The container must be an owning container.
2925 *
2926 * Note: this method may only be called using the most derived
2927 * @c DataVector in the hierarchy.
2928 *
2929 * Returns the pushed pointer.
2930 */
2931template <class T>
2932inline
2933typename DATAVECTOR::value_type
2934DATAVECTOR::push_back(std::unique_ptr<base_value_type> pElem)
2935{
2936 // Container must own its elements.
2937 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
2938 SG::throwExcNonowningContainer();
2939
2940 // Ensure we're not being called via a base class.
2941 testInsert ("push_back");
2942 value_type ptr = pElem.release();
2943 m_pCont.push_back(ptr);
2944 SG::AuxVectorBase::resize<DataVector> (this->size());
2945 if (ptr && this->trackIndices())
2946 this->moveAuxNoClear (this->size()-1, ptr);
2947 return ptr;
2948}
2949
2950
2951/**
2952 * @brief Create and add a number of new elements to the end of the container.
2953 * @param n The number of new elements to add.
2954 * @param alloc Functional to call to allocate a new element to push.
2955 * Should be callable like <code>T* = alloc();</code>
2956 * For example:
2957 *@code
2958 * dv.push_new (n, [](){ return new Foo; });
2959 @endcode
2960 * It may also be useful to allocate from a @c DataPool.
2961 *
2962 * Note: this method may only be called using the most derived
2963 * @c DataVector in the hierarchy.
2964 *
2965 * Returns the original size of the vector.
2966 */
2967template <class T>
2968template <CxxUtils::detail::AllocationFunction<T> F>
2969auto
2970DATAVECTOR::push_new(size_type n, F alloc) -> size_type
2971{
2972 // Ensure we're not being called via a base class.
2973 testInsert ("push_new");
2974 bool trackIndices = this->trackIndices();
2975
2976 size_t sz = this->m_pCont.size();
2977 this->m_pCont.resize (sz + n);
2978 SG::AuxVectorBase::resize<DataVector> (this->size());
2979 for (size_t i = 0; i < n; i++) {
2980 T* p = alloc();
2981 this->m_pCont[sz+i] = p;
2982 if (trackIndices) {
2983 this->moveAuxNoClear (sz+i, p);
2984 }
2985 }
2986 return sz;
2987}
2988
2989
2990/**
2991 * @brief Add an element to the end of the collection.
2992 * @param pElem The element to add to the collection.
2993 *
2994 * The container's ownership policy will determine if it takes ownership
2995 * of the new element.
2996 *
2997 * Note: this method may only be called using the most derived
2998 * @c DataVector in the hierarchy.
2999 *
3000 * For @c DataVector, this is like the same as @c push_back, and
3001 * it returns the pushed element.
3002 * It's included just for interface compatibility with `std::vector`.
3003 */
3004template <class T>
3005inline
3006typename DATAVECTOR::value_type
3007DATAVECTOR::emplace_back(value_type pElem)
3008{
3009 return this->push_back (pElem);
3010}
3011
3012
3013/**
3014 * @brief Add a new element to the collection.
3015 * @param position Iterator before which the element will be added.
3016 * @param pElem The element to add to the collection.
3017 * @return An iterator that points to the inserted data.
3018 *
3019 * The container's ownership policy will determine if it takes ownership
3020 * of the new element.
3021 *
3022 * Note: this method may only be called using the most derived
3023 * @c DataVector in the hierarchy.
3024 */
3025template <class T>
3026inline
3027typename DATAVECTOR::iterator
3028DATAVECTOR::insert(iterator position, value_type pElem)
3029{
3030 // Ensure we're not being called via a base class.
3031 testInsert ("insert");
3032 iterator ret (m_pCont.insert(position.base(), pElem), this);
3033 this->shift (ret - this->begin(), 1);
3034 if (this->trackIndices())
3035 this->moveAuxNoClear (ret-this->begin(), pElem);
3036 return ret;
3037}
3038
3039
3040/**
3041 * @brief Add a new element to the collection.
3042 * @param position Iterator before which the element will be added.
3043 * @param pElem The element to add to the collection.
3044 * @return An iterator that points to the inserted data.
3045 *
3046 * The container must be an owning container.
3047 *
3048 * Note: this method may only be called using the most derived
3049 * @c DataVector in the hierarchy.
3050 */
3051template <class T>
3052inline
3053typename DATAVECTOR::iterator
3054DATAVECTOR::insert(iterator position, std::unique_ptr<base_value_type> pElem)
3055{
3056 // Container must own its elements.
3057 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3058 SG::throwExcNonowningContainer();
3059
3060 // Ensure we're not being called via a base class.
3061 testInsert ("insert");
3062 value_type ptr = pElem.release();
3063 iterator ret (m_pCont.insert(position.base(), ptr), this);
3064 this->shift (ret - this->begin(), 1);
3065 if (this->trackIndices())
3066 this->moveAuxNoClear (ret-this->begin(), ptr);
3067 return ret;
3068}
3069
3070
3071/**
3072 * @brief Add a new element to the collection.
3073 * @param position Iterator before which the element will be added.
3074 * @param pElem The element to add to the collection.
3075 * @return An iterator that points to the inserted data.
3076 *
3077 * The container's ownership policy will determine if it takes ownership
3078 * of the new element.
3079 *
3080 * Note: this method may only be called using the most derived
3081 * @c DataVector in the hierarchy.
3082 *
3083 * For @c DataVector, this is just the same as @c insert.
3084 * It's included just for interface compatibility with `std::vector`.
3085 */
3086template <class T>
3087inline
3088typename DATAVECTOR::iterator
3089DATAVECTOR::emplace(iterator position, value_type pElem)
3090{
3091 return this->insert (position, pElem);
3092}
3093
3094
3095/**
3096 * @brief Add a group of new elements to the collection.
3097 * @param position Iterator before which the element will be added.
3098 * @param first The start of the range to put in the container.
3099 * @param last The end of the range to put in the container.
3100 *
3101 * The container's ownership policy will determine if it takes ownership
3102 * of the new element.
3103 *
3104 * Note: this method may only be called using the most derived
3105 * @c DataVector in the hierarchy.
3106 *
3107 * This overload is for the case where the iterator value type
3108 * is convertible to T*.
3109 */
3110template <class T>
3111template <class InputIterator,
3112 DataVector_detail::enable_if_ptr_itr<InputIterator, T> >
3113inline
3114void
3115DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3116{
3117 static_assert (std::is_same_v<T*, typename DATAVECTOR::value_type>);
3118 // Ensure we're not being called via a base class.
3119 testInsert ("insert");
3120 size_t idx = position - this->begin();
3121 size_t old_sz = this->m_pCont.size();
3122 m_pCont.insert(position.base(), first, last);
3123 size_t n = this->m_pCont.size() - old_sz;
3124 this->shift (idx, n);
3125 this->moveAux (idx, first, last, false, true);
3126}
3127
3128
3129/**
3130 * @brief Add a group of new elements to the collection.
3131 * @param position Iterator before which the element will be added.
3132 * @param first The start of the range to put in the container.
3133 * @param last The end of the range to put in the container.
3134 *
3135 * The container's ownership policy will determine if it takes ownership
3136 * of the new element.
3137 *
3138 * Note: this method may only be called using the most derived
3139 * @c DataVector in the hierarchy.
3140 *
3141 * This overload is for the case where the iterator value type
3142 * is convertible to unique_ptr<T>.
3143 */
3144template <class T>
3145template <class InputIterator,
3146 DataVector_detail::enable_if_up_itr<InputIterator, T> >
3147inline
3148void
3149DATAVECTOR::insert (iterator position, InputIterator first, InputIterator last)
3150{
3151 // Ensure we're not being called via a base class.
3152 testInsert ("insert");
3153 size_t idx = position - this->begin();
3154 size_t old_sz = this->m_pCont.size();
3155 using CxxUtils::releasing_iterator;
3156 m_pCont.insert(position.base(), releasing_iterator(first), releasing_iterator(last));
3157 size_t n = this->m_pCont.size() - old_sz;
3158 this->shift (idx, n);
3159 this->moveAux (idx, this->begin()+idx, this->begin()+idx+n);
3160}
3161
3162
3163/**
3164 * @brief Add a group of new elements to the collection.
3165 * @param position Iterator before which the element will be added.
3166 * @param l An initializer list.
3167 *
3168 * The container's ownership policy will determine if it takes ownership
3169 * of the new element.
3170 *
3171 * Note: this method may only be called using the most derived
3172 * @c DataVector in the hierarchy.
3173 */
3174template <class T>
3175inline
3176void
3177DATAVECTOR::insert (iterator position, std::initializer_list<value_type> l)
3178{
3179 this->insert (position, l.begin(), l.end());
3180}
3181
3182
3183/**
3184 * @brief Insert the contents of another @c DataVector,
3185 * with auxiliary data copied via move semantics.
3186 * @param position Iterator before which the new elements will be added.
3187 * @param other The vector to add.
3188 *
3189 * The ownership mode of this vector must be the same as @c other;
3190 * otherwise, an exception will be thrown.
3191 *
3192 * If both vectors are view vectors, then this is the same
3193 * as <code> insert (position, other.begin(), other.end()) </code>.
3194 *
3195 * Otherwise, the elements from @c other will be inserted into this vector.
3196 * This vector will take ownership of the elements, and the ownership
3197 * mode of @c other will be changed to @c VIEW_ELEMENTS.
3198 * Auxiliary data for these elements will be transferred,
3199 * using move semantics if possible. (Thus, the auxiliary store
3200 * for @c other may be modified and must not be locked.)
3201 * Finally, the auxiliary store pointer for @c other will be cleared
3202 * (but the store itself will not be deleted since it's not owned
3203 * by the vector).
3204 *
3205 * Note: this method may only be called using the most derived
3206 * @c DataVector in the hierarchy.
3207 */
3208template <class T>
3209void
3210DATAVECTOR::insertMove (iterator position, DataVector& other)
3211{
3212 if (this->m_ownPolicy != other.ownPolicy())
3213 throw SG::ExcInsertMoveOwnershipMismatch();
3214
3215 if (this->m_ownPolicy == SG::VIEW_ELEMENTS) {
3216 this->insert (position, other.begin(), other.end());
3217 return;
3218 }
3219
3220 testInsert ("insertMove");
3221 size_t pos = position.base() - this->m_pCont.begin();
3222 this->m_pCont.insert (position.base(), other.begin(), other.end());
3223 this->setIndices (this->begin()+pos, this->end(), pos);
3224 other.m_ownPolicy = SG::VIEW_ELEMENTS;
3225
3226 SG::IAuxStore* otherStore = other.getStore();
3227 if (otherStore) {
3228 SG::IAuxStore* store = this->getStore();
3229 if (store) {
3230 if (!store->insertMove (pos, *otherStore))
3231 this->clearCache();
3232 }
3233 else if (this->hasStore())
3234 throw SG::ExcConstAuxData ("insertMove");
3235 other.setStore (static_cast<SG::IAuxStore*>(nullptr));
3236 }
3237 else if (other.hasStore())
3238 throw SG::ExcConstAuxData ("insertMove");
3239}
3240
3241
3242//=== Erasure operations.
3243
3244
3245/**
3246 * @brief Remove element at a given position.
3247 * @param position Iterator pointing to the element to be removed.
3248 * @return An iterator pointing to the next element (or @c end()).
3249 *
3250 * If the container owns its elements, then the pointed-to element
3251 * will be deleted.
3252 */
3253template <class T>
3254inline
3255typename DATAVECTOR::iterator DATAVECTOR::erase(iterator position)
3256{
3257 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3258 this->clearIndex (position);
3259 iterator ret (this->erase_base (position.base()), this);
3260 this->shift (ret - this->begin() + 1, -1);
3261 return ret;
3262}
3263
3264
3265/**
3266 * @brief Remove a range of elements.
3267 * @param first Iterator pointing to the first element to be removed.
3268 * @param last Iterator pointing one past the last element to be removed.
3269 * @return An iterator pointing to the element pointed to by @a last
3270 * prior to erasing (or @c end()).
3271 *
3272 * If the container owns its elements, then the removed elements
3273 * will be deleted. Any duplicates will be removed in this process,
3274 * but don't rely on this.
3275 */
3276template <class T>
3277inline
3278typename DATAVECTOR::iterator DATAVECTOR::erase(iterator first, iterator last)
3279{
3280 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3281 this->clearIndices (first, last);
3282 iterator ret (this->erase_base (first.base(), last.base()), this);
3283 this->shift (ret - this->begin() + (last-first), -(last-first));
3284 return ret;
3285}
3286
3287
3288/**
3289 * @brief Remove the last element from the collection.
3290 *
3291 * If the container owns its elements, then the removed element
3292 * will be deleted.
3293 */
3294template <class T>
3295void DATAVECTOR::pop_back()
3296{
3297 if (!m_pCont.empty()) {
3298 if (m_ownPolicy == SG::OWN_ELEMENTS)
3299 this->doDelete (m_pCont.back());
3300 else
3301 this->clearIndex (m_pCont.end() - 1);
3302 m_pCont.pop_back();
3303 SG::AuxVectorBase::resize<DataVector> (this->m_pCont.size());
3304 }
3305}
3306
3307
3308/**
3309 * @brief Erase all the elements in the collection.
3310 *
3311 * If the container owns its elements, then the removed elements
3312 * will be deleted. Any duplicates will be removed in this process,
3313 * but don't rely on this.
3314 */
3315template <class T>
3316inline
3317void DATAVECTOR::clear()
3318{
3319 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3320 this->clearIndices (begin(), end());
3321 this->erase_base (m_pCont.begin(), m_pCont.end());
3322 SG::AuxVectorBase::resize<DataVector> (0);
3323}
3324
3325
3326//=== Swap and sort.
3327
3328
3329/**
3330 * @brief Swap this collection with another.
3331 * @param rhs The collection with which to swap.
3332 *
3333 * Ownership is swapped along with the collection content.
3334 *
3335 * Note: this method may only be called using the most-derived
3336 * @c DataVector in the hierarchy. The @a rhs must also be
3337 * referenced using the most-derived @c DataVector.
3338 *
3339 * Warning: If this container has auxiliary data, then this
3340 * is an O(N) operation, not O(1).
3341 */
3342template <class T>
3343void DATAVECTOR::swap(DataVector& rhs)
3344{
3345 testInsert ("swap");
3346 rhs.testInsert ("swap");
3347 std::swap(m_ownPolicy, rhs.m_ownPolicy);
3348 SG::AuxVectorBase::swap (rhs);
3349 m_pCont.swap(rhs.m_pCont);
3350 std::swap (this->m_deleter, rhs.m_deleter);
3351 this->setIndices (this->begin(), this->end());
3352 rhs.setIndices (rhs.begin(), rhs.end());
3353}
3354
3355
3356/**
3357 * @brief Swap the referents of two @c DataVector iterators.
3358 * @param a The first iterator for the swap.
3359 * @param b The second iterator for the swap.
3360 */
3361template <class T>
3362void DATAVECTOR::iter_swap (iterator a, iterator b)
3363{
3364 if (a.ownPolicy() != b.ownPolicy()) {
3365 throw SG::ExcBadIterSwap();
3366 }
3367 a.testInsert ("iter_swap");
3368 b.testInsert ("iter_swap");
3369 std::iter_swap (a.base(), b.base());
3370 DataVector* acont = a.container();
3371 DataVector* bcont = b.container();
3372 if (typename SG::AuxStore_traits<DataVector>::flag())
3373 acont->swapElementsAux (a.base() - acont->stdcont().begin(),
3374 b.base() - bcont->stdcont().begin(),
3375 *a.base(),
3376 *b.base(),
3377 bcont);
3378}
3379
3380
3381/**
3382 * @brief Sort the container.
3383 *
3384 * This just sorts by pointer value, so it's probably not very useful.
3385 */
3386template <class T>
3387void DATAVECTOR::sort()
3388{
3389 std::sort(m_pCont.begin(), m_pCont.end());
3390 this->resortAux (this->begin(), this->end());
3391}
3392
3393
3394/**
3395 * @brief Sort the container with a user-specified comparison operator.
3396 * @param comp Functional to compare two values.
3397 */
3398template <class T>
3399template <class COMPARE>
3400void DATAVECTOR::sort(COMPARE comp)
3401{
3402 std::sort(m_pCont.begin(), m_pCont.end(), comp);
3403 this->resortAux (this->begin(), this->end());
3404}
3405
3406
3407//=== Non-standard operations.
3408
3409
3410/**
3411 * @brief Swap one element out of the container.
3412 * @param index Index of the element in the container to swap.
3413 * @param newElement New element to put in the container.
3414 * May be 0.
3415 * @param oldElem Reference to receive the element removed from the
3416 * container.
3417 *
3418 * Reference @a oldElem is initialized with element @a index of the
3419 * collection (no bounds checking). Then element @a index is set
3420 * to @newElem. If the collection owns its elements, then it will
3421 * take ownership of @a newElem and release (without deleting)
3422 * the element returned through @a oldElem.
3423 *
3424 * Note: this method may only be called using the most derived
3425 * @c DataVector in the hierarchy.
3426 */
3427template <class T>
3428void
3429DATAVECTOR::swapElement (size_type index,
3430 value_type newElem,
3431 reference oldElem)
3432{
3433 testInsert ("swapElement");
3434 oldElem = m_pCont[index];
3435 this->clearIndex (iterator (m_pCont.begin() + index, this));
3436 m_pCont[index] = newElem;
3437 this->moveAux (index, newElem);
3438}
3439
3440
3441/**
3442 * @brief Swap one element out of the container.
3443 * @param pos The element in the container to swap.
3444 * @param newElem New element to put in the container.
3445 * May be 0.
3446 * @param oldElem Reference to receive the element removed from the
3447 * container.
3448 *
3449 * Reference @a oldElem is initialized with element @a pos of the
3450 * collection (no bounds checking). Then element @a index is set
3451 * to @c newElem. If the collection owns its elements, then it will
3452 * take ownership of @a newElem and release (without deleting)
3453 * the element returned through @a oldElem.
3454 *
3455 * Note: this method may only be called using the most derived
3456 * @c DataVector in the hierarchy.
3457 */
3458template <class T>
3459void
3460DATAVECTOR::swapElement (iterator pos,
3461 value_type newElem,
3462 reference oldElem)
3463{
3464 testInsert ("swapElement");
3465 oldElem = *pos.base();
3466 this->clearIndex (pos);
3467 *pos.base() = newElem;
3468 this->moveAux (pos.base() - this->m_pCont.begin(), newElem);
3469}
3470
3471
3472/**
3473 * @brief Swap one element out of the container.
3474 * @param index Index of the element in the container to swap.
3475 * @param newElement New element to put in the container.
3476 * May be 0.
3477 * @param oldElem Reference to receive the element removed from the
3478 * container.
3479 *
3480 * Reference @a oldElem is initialized with element @a index of the
3481 * collection (no bounds checking). Then element @a index is set
3482 * to @newElem.
3483 *
3484 * The collection must own its elements to use its interface.
3485 * The collection will take ownership of @c newElem and will return
3486 * ownership of @c oldElem.
3487 *
3488 * Note: this method may only be called using the most derived
3489 * @c DataVector in the hierarchy.
3490 */
3491template <class T>
3492void
3493DATAVECTOR::swapElement (size_type index,
3494 std::unique_ptr<base_value_type> newElem,
3495 std::unique_ptr<base_value_type>& oldElem)
3496{
3497 // Container must own its elements.
3498 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3499 SG::throwExcNonowningContainer();
3500
3501 testInsert ("swapElement");
3502 oldElem = std::unique_ptr<base_value_type> (m_pCont[index]);
3503 this->clearIndex (iterator (m_pCont.begin() + index, this));
3504 value_type ptr = newElem.release();
3505 m_pCont[index] = ptr;
3506 this->moveAux (index, ptr);
3507}
3508
3509
3510/**
3511 * @brief Swap one element out of the container.
3512 * @param pos The element in the container to swap.
3513 * @param newElem New element to put in the container.
3514 * May be 0.
3515 * @param oldElem Reference to receive the element removed from the
3516 * container.
3517 *
3518 * Reference @a oldElem is initialized with element @a pos of the
3519 * collection (no bounds checking). Then element @a index is set
3520 * to @c newElem.
3521 *
3522 * The collection must own its elements to use its interface.
3523 * The collection will take ownership of @c newElem and will return
3524 * ownership of @c oldElem.
3525 *
3526 * Note: this method may only be called using the most derived
3527 * @c DataVector in the hierarchy.
3528 */
3529template <class T>
3530void
3531DATAVECTOR::swapElement (iterator pos,
3532 std::unique_ptr<base_value_type> newElem,
3533 std::unique_ptr<base_value_type>& oldElem)
3534{
3535 // Container must own its elements.
3536 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3537 SG::throwExcNonowningContainer();
3538
3539 testInsert ("swapElement");
3540 oldElem = std::unique_ptr<base_value_type> (*pos.base());
3541 this->clearIndex (pos);
3542 value_type ptr = newElem.release();
3543 *pos.base() = ptr;
3544 this->moveAux (pos.base() - this->m_pCont.begin(), ptr);
3545}
3546
3547
3548/**
3549 * @brief Return the underlying @c std::vector of the container.
3550 * @return Reference to the @c std::vector actually holding the collection.
3551 *
3552 * Note that @c DataVector<T>::stdcont does not necessarily return
3553 * a @c std::vector<T*> if @c DataVector inheritance is being used.
3554 */
3555template <class T>
3556inline
3557const typename DATAVECTOR::PtrVector& DATAVECTOR::stdcont() const
3558{
3559 return m_pCont;
3560}
3561
3562
3563/**
3564 * @brief Return the ownership policy setting for this container.
3565 */
3566template <class T>
3567inline
3568SG::OwnershipPolicy DATAVECTOR::ownPolicy() const
3569{
3570 return m_ownPolicy;
3571}
3572
3573
3574/**
3575 * @brief Erase all the elements in the collection, and reset
3576 * the ownership mode.
3577 * @param ownPolicy The new ownership policy of the container.
3578 * @param trackIndices The index tracking policy.
3579 *
3580 * If the container owns its elements, then the removed elements
3581 * will be deleted. Any duplicates will be removed in this process,
3582 * but don't rely on this.
3583 */
3584template <class T>
3585void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy)
3586{
3587 clear();
3588 m_ownPolicy = ownPolicy;
3589 this->template initAuxVectorBase<DataVector> (ownPolicy,
3590 SG::DEFAULT_TRACK_INDICES);
3591}
3592
3593
3594/**
3595 * @brief Erase all the elements in the collection, and reset
3596 * the ownership mode.
3597 * @param ownPolicy The new ownership policy of the container.
3598 * @param trackIndices The index tracking policy.
3599 *
3600 * If the container owns its elements, then the removed elements
3601 * will be deleted. Any duplicates will be removed in this process,
3602 * but don't rely on this.
3603 */
3604template <class T>
3605void DATAVECTOR::clear (SG::OwnershipPolicy ownPolicy,
3606 SG::IndexTrackingPolicy trackIndices)
3607{
3608 clear();
3609 m_ownPolicy = ownPolicy;
3610 this->template initAuxVectorBase<DataVector> (ownPolicy, trackIndices);
3611}
3612
3613
3614/**
3615 * @brief Return the DV/DL info struct for this class.
3616 *
3617 * This can be used to make sure that it's instantiated.
3618 */
3619template <class T>
3620const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo()
3621{
3622 static const DataModel_detail::DVLInfo<DataVector<T, DataModel_detail::NoBase> > info;
3623 return info;
3624}
3625
3626
3627/**
3628 * @brief Erase all the elements in the collection, and change
3629 * how elements are to be deleted.
3630 * @param deleter Object to be used to delete object.
3631 * (The DataVector does not take ownership.)
3632 * Passing nullptr will change back to the default.
3633 *
3634 * If the container owns its elements, then the removed elements
3635 * will be deleted. Any duplicates will be removed in this process,
3636 * but don't rely on this.
3637 * After the current elements are deleted, the Deleter object is changed.
3638 */
3639template <class T>
3640void DATAVECTOR::clear (std::unique_ptr<Deleter> deleter)
3641{
3642 this->clear();
3643 delete this->m_deleter;
3644 this->m_deleter = deleter.release();
3645}
3646
3647
3648/**
3649 * @brief Return the DV/DL info struct for this class.
3650 *
3651 * This can be used to make sure that it's instantiated.
3652 */
3653template <class T>
3654const DataModel_detail::DVLInfoBase& DATAVECTOR::dvlinfo_v() const
3655{
3656 return DATAVECTOR::dvlinfo();
3657}
3658
3659
3660/**
3661 * @brief Return the offset of a base @c DataVector class.
3662 * @param ti @c std::type_info of the desired class.
3663 *
3664 * If @c ti represents a @c DataVector base class of this one,
3665 * then return the offset of that base class. Otherwise, return -1.
3666 *
3667 * This function is here due to limitations of root 6, which can't
3668 * calculate these offsets correctly from the dictionary if
3669 * virtual derivation is used.
3670 */
3671template <class T>
3672int DATAVECTOR::baseOffset (const std::type_info& ti)
3673{
3674 if (typeid(DataVector) == ti)
3675 return 0;
3676 return -1;
3677}
3678
3679
3680/**
3681 * @brief Convert to @c AuxVectorBase.
3682 *
3683 * Needed to get @x AuxVectorBase from a @c ConstDataVector.
3684 * Present in @c DataVector as well for consistency.
3685 */
3686template <class T>
3687inline
3688const SG::AuxVectorBase& DATAVECTOR::auxbase() const
3689{
3690 return *this;
3691}
3692
3693
3694//=== Internal operations.
3695
3696
3697/**
3698 * @brief Helper for @c baseOffset.
3699 * @param p Pointer to the start of the top-level object.
3700 * @param dv Reference to the DataVector object.
3701 * @param ti @c std::type_info of the desired class.
3702 *
3703 * If @c ti represents a @c DataVector base class of this one,
3704 * then return the offset of that base class. Otherwise, return -1.
3705 *
3706 */
3707template <class T>
3708int DATAVECTOR::baseOffset1 (const char* p, const DataVector& dv,
3709 const std::type_info& ti)
3710{
3711 if (typeid(DataVector) == ti)
3712 return reinterpret_cast<const char*>(&dv) - p;
3713 return -1;
3714}
3715
3716
3717/**
3718 * @brief Reset indices / reorder aux data after elements have been permuted.
3719 * @param beg Start of the range of elements to process.
3720 * @param end End of the range of elements to process.
3721 *
3722 * Call this after some operation that has permuted the elements in the
3723 * container (such as sort). The index information in the elements
3724 * will be used to permute all auxiliary data in the same way.
3725 * Finally, all the indices will be reset in the correct order.
3726 */
3727template <class T>
3728void DATAVECTOR::resortAux (iterator beg, iterator end)
3729{
3730 if (typename SG::AuxStore_traits<DataVector>::flag() &&
3731 beg >= this->begin() && end <= this->end())
3732 {
3733 SG::AuxVectorBase::resortAux (beg-begin(), beg, end);
3734 }
3735}
3736
3737
3738/**
3739 * @brief Handle element assignment.
3740 * @param pos Position in the container to assign.
3741 * @param newElem The new element to assign.
3742 *
3743 * The old element is freed if this container owns elements.
3744 * Auxiliary data are copied if appropriate.
3745 */
3746template <class T>
3747void DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3748 value_type newElem)
3749{
3750 testInsert ("assignElement");
3751 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3752 this->doDelete (*pos);
3753 else
3754 this->clearIndex (iterator (pos, this));
3755 *pos = newElem;
3756 this->moveAux (pos - this->m_pCont.begin(), newElem);
3757}
3758
3759
3760/**
3761 * @brief Handle element assignment.
3762 * @param pos Position in the container to assign.
3763 * @param newElem The new element to assign.
3764 *
3765 * The container must own its elements.
3766 * Auxiliary data are copied if appropriate.
3767 */
3768template <class T>
3769void
3770DATAVECTOR::assignElement (typename BaseContainer::iterator pos,
3771 std::unique_ptr<base_value_type> newElem)
3772{
3773 // Container must own its elements.
3774 if (this->m_ownPolicy != SG::OWN_ELEMENTS)
3775 SG::throwExcNonowningContainer();
3776
3777 testInsert ("assignElement");
3778 this->doDelete (*pos);
3779 value_type ptr = newElem.release();
3780 *pos = ptr;
3781 this->moveAux (pos - this->m_pCont.begin(), ptr);
3782}
3783
3784
3785/**
3786 * @brief Handle element assignment from a base pointer.
3787 * @param pos Position in the container to assign.
3788 * @param newElem The new element to assign.
3789 *
3790 * The old element is freed if this container owns elements.
3791 * Auxiliary data are copied if appropriate.
3792 */
3793template <class T>
3794void DATAVECTOR::assignBaseElement (typename BaseContainer::iterator pos,
3795 typename BaseContainer::value_type newElem)
3796{
3797 testInsert ("assignBaseElement");
3798 if (this->m_ownPolicy == SG::OWN_ELEMENTS)
3799 this->doDelete (*pos);
3800 else
3801 this->clearIndex (iterator (pos, this));
3802 *pos = newElem;
3803 if (typename SG::AuxStore_traits<DataVector>::flag())
3804 this->moveAux (pos - this->m_pCont.begin(), newElem);
3805}
3806
3807
3808/**
3809 * @brief Shift the auxiliary elements of the container.
3810 * @param pos The starting index for the shift.
3811 * @param offs The (signed) amount of the shift.
3812 *
3813 * The elements in the container should have already been shifted;
3814 * this operation will then adjust the element indices and also shift
3815 * the elements in the vectors for all aux data items.
3816 * @c offs may be either positive or negative.
3817 *
3818 * If @c offs is positive, then the container is growing.
3819 * The container size should be increased by @c offs,
3820 * the element at @c pos moved to @c pos + @c offs,
3821 * and similarly for following elements.
3822 * The elements between @c pos and @c pos + @c offs should
3823 * be default-initialized.
3824 *
3825 * If @c offs is negative, then the container is shrinking.
3826 * The element at @c pos should be moved to @c pos + @c offs,
3827 * and similarly for following elements.
3828 * The container should then be shrunk by @c -offs elements
3829 * (running destructors as appropriate).
3830 */
3831template <class T>
3832void DATAVECTOR::shift (size_t pos, ptrdiff_t offs)
3833{
3834 SG::AuxVectorBase::shift (*this, pos, offs);
3835}
3836
3837
3838/**
3839 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3840 * @param p The value to convert.
3841 * @return The value as a @c const @c T*.
3842 *
3843 * This is a no-op for the base class.
3844 */
3845template <class T>
3846inline
3847const T* DATAVECTOR::do_cast (const typename PtrVector::value_type p)
3848{
3849 return p;
3850}
3851
3852
3853/**
3854 * @brief Helper to shorten calls to @c DataModel_detail::DVLCast.
3855 * @param p The value to convert.
3856 * @return The value as a @c T*.
3857 *
3858 * This is a no-op for the base class.
3859 */
3860template <class T>
3861inline
3862T* DATAVECTOR::do_cast_nc (typename PtrVector::value_type p)
3863{
3864 return p;
3865}
3866
3867
3868/**
3869 * @brief Find the most-derived @c DataVector class in the hierarchy.
3870 * @return The @c type_info for the class for which this method gets run.
3871 *
3872 * This is used to generate a nice error message when the most-derived
3873 * check for insertions fails.
3874 * Every @c DataVector defines this virtual method, so when it's
3875 * called, the one corresponding to the most-derived @c DataVector
3876 * gets run.
3877 */
3878template <class T>
3879const std::type_info& DATAVECTOR::dv_typeid() const
3880{
3881 return typeid(DataVector);
3882}
3883
3884
3885/**
3886 * @brief Helper for @c erase(). Remove element at a given position.
3887 * @param position Iterator pointing to the element to be removed.
3888 * @return An iterator pointing to the next element (or @c end()).
3889 *
3890 * This function factors out common code between @c erase() in the
3891 * base and derived @c DataVector classes. It deals with the
3892 * @c std::vector iterators directly.
3893 */
3894template <class T>
3895typename DATAVECTOR::PtrVector::iterator
3896DATAVECTOR::erase_base(typename PtrVector::iterator position)
3897{
3898 if (m_ownPolicy == SG::OWN_ELEMENTS && position != m_pCont.end())
3899 this->doDelete (*position);
3900 return m_pCont.erase(position);
3901}
3902
3903
3904/**
3905 * @brief Helper for @c erase(). Remove a range of elements.
3906 * @param first Iterator pointing to the first element to be removed.
3907 * @param last Iterator pointing one past the last element to be removed.
3908 * @return An iterator pointing to the element pointed to by @a last
3909 * prior to erasing (or @c end()).
3910 *
3911 * This function factors out common code between @c erase() in the
3912 * base and derived @c DataVector classes. It deals with the
3913 * @c std::vector iterators directly.
3914 */
3915template <class T>
3916typename DATAVECTOR::PtrVector::iterator
3917DATAVECTOR::erase_base(typename PtrVector::iterator first,
3918 typename PtrVector::iterator last)
3919{
3920 if (first == last) return first;
3921 if (m_ownPolicy == SG::OWN_ELEMENTS) {
3922 typename PtrVector::iterator new_end =
3923 DataVector_detail::remove_duplicates(first, last);
3924 this->doDelete (first, new_end);
3925 }
3926 return m_pCont.erase(first, last);
3927}
3928
3929
3930/**
3931 * @brief Delete an element
3932 * @param p The element to delete.
3933 */
3934template <class T>
3935inline
3936void DATAVECTOR::doDelete (value_type p)
3937{
3938 if (m_deleter) {
3939 m_deleter->doDelete (p);
3940 }
3941 else {
3942 delete p;
3943 }
3944}
3945
3946
3947/**
3948 * @brief Delete a range of elements
3949 * @param first Start of range to delete.
3950 * @param last End of range to delete.
3951 */
3952template <class T>
3953inline
3954void DATAVECTOR::doDelete (typename PtrVector::iterator first,
3955 typename PtrVector::iterator last)
3956{
3957 if (m_deleter) {
3958 m_deleter->doDelete (first, last);
3959 }
3960 else {
3961 for (; first != last; ++first) {
3962 delete *first;
3963 }
3964 }
3965}
3966
3967
3968/**
3969 * @brief Test if we can insert; raise an exception if not.
3970 * @param op Description of the attempted operation.
3971 *
3972 * In order to maintain type-safety, we can only allow insertions
3973 * using the most-derived instance of @c DataVector. This checks
3974 * this by testing the @c m_isMostDerived, which is set by the constructors
3975 * to true only for the most-derived instance.
3976 * If the test fails, we call to potentially out-of-line code to continue.
3977 */
3978template <class T>
3979inline
3980void DATAVECTOR::testInsert (const char* op)
3981{
3982 if (ATHCONTAINERS_LIKELY (m_isMostDerived))
3983 return;
3984 this->testInsertOol (op);
3985}
3986
3987
3988/**
3989 * @brief Test if we can insert; raise an exception if not.
3990 * @param op Description of the attempted operation.
3991 *
3992 * This continues the test of @c testInsert. There is one case
3993 * where @c m_isMostDerived may not be set correctly. If this container
3994 * was made via copy construction, then all the @c m_isMostDerived flags
3995 * will be false. So we call @c setMostDerived to set the flags correctly
3996 * and test again. If the test fails again, then we raise an exception.
3997 */
3998template <class T>
3999void DATAVECTOR::testInsertOol (const char* op)
4000{
4001 this->setMostDerived();
4002 if (!m_isMostDerived)
4003 throw SG::ExcInsertionInBaseClass (op, typeid(DataVector), dv_typeid());
4004}
4005
4006
4007/**
4008 * @brief Clear @c m_isMostDerived for this instance and for all bases.
4009 *
4010 * Called from the constructor after setting @c m_isMostDerived.
4011 */
4012template <class T>
4013inline
4014void DATAVECTOR::clearMostDerived()
4015{
4016 this->m_isMostDerived = false;
4017}
4018
4019
4020/**
4021 * @brief Set @c m_isMostDerived for this instance and clear it for all bases.
4022 *
4023 * Called from @c testInsert if the test fails. The flag may not have
4024 * been set if this container was made via copy construction, so set
4025 * it appropriately now so we can test again.
4026 */
4027template <class T>
4028void DATAVECTOR::setMostDerived()
4029{
4030 m_isMostDerived = true;
4031}
4032
4033
4034#undef DATAVECTOR
4035
4036
4037//****************************************************************************
4038// Free function implementations.
4039//
4040
4041
4042/**
4043 * @brief Vector equality comparison.
4044 * @param a A @c DataVector.
4045 * @param b A @c DataVector of the same type as @a b.
4046 * @return True iff the size and elements of the vectors are equal.
4047 *
4048 * This is an equivalence relation. It is linear in the size of the
4049 * vectors. Vectors are considered equivalent if their sizes are equal,
4050 * and if corresponding elements compare equal.
4051 */
4052template <class T>
4053bool operator== (const DataVector<T>& a, const DataVector<T>& b)
4054{
4055 return a.stdcont() == b.stdcont();
4056}
4057
4058
4059/// Based on operator==
4060template <class T>
4061bool operator!= (const DataVector<T>& a, const DataVector<T>& b)
4062{
4063 return a.stdcont() != b.stdcont();
4064}
4065
4066
4067/**
4068 * @brief Vector ordering relation.
4069 * @param a A @c DataVector.
4070 * @param b A @c DataVector of the same type as @a x.
4071 * @return True iff @a a is lexicographically less than @a b.
4072 *
4073 * This is a total ordering relation. It is linear in the size of the
4074 * vectors. Comparisons are done on the pointer values of the elements.
4075 *
4076 * See @c std::lexicographical_compare() for how the determination is made.
4077 */
4078template <class T>
4079bool operator< (const DataVector<T>& a, const DataVector<T>& b)
4080{
4081 return a.stdcont() < b.stdcont();
4082}
4083
4084
4085/// Based on operator<
4086template <class T>
4087bool operator> (const DataVector<T>& a, const DataVector<T>& b)
4088{
4089 return a.stdcont() > b.stdcont();
4090}
4091
4092
4093/// Based on operator<
4094template <class T>
4095bool operator<= (const DataVector<T>& a, const DataVector<T>& b)
4096{
4097 return a.stdcont() <= b.stdcont();
4098}
4099
4100
4101/// Based on operator<
4102template <class T>
4103bool operator>= (const DataVector<T>& a, const DataVector<T>& b)
4104{
4105 return a.stdcont() >= b.stdcont();
4106}
4107
4108
4109/// See @c DataVector<T, BASE>::swap().
4110template <class T>
4111void swap (DataVector<T>& a, DataVector<T>& b)
4112{
4113 a.swap (b);
4114}
4115
4116
4117/**
4118 * @brief Specialization of @c ClassName for @c DataVector.
4119 *
4120 * This overrides the default implementation of @c ClassName
4121 * to hide @c DataVector's second template parameter.
4122 */
4123template <class T>
4124std::string ClassName<DataVector<T> >::name()
4125{
4126 std::string out = "DataVector<";
4127 out += ClassName<T>::name();
4128 if (out[out.size()-1] == '>')
4129 out += ' ';
4130 out += '>';
4131 return out;
4132}
4133
4134
4135#ifndef XAOD_STANDALONE
4136
4137
4138// Set up initialization of element type BaseInfo
4139namespace DataVector_detail {
4140#define DVLTYPE DataVector
4141#include "AthContainers/tools/DVLEltBaseInfo.icc"
4142#undef DVLTYPE
4143} // namespace DataVector_detail
4144
4145
4146#else
4147
4148
4149namespace DataVector_detail {
4150/// Dummy implementation for the DVLEltBaseInit structure
4151template< class T >
4152struct DVLEltBaseInit {};
4153} // namespace DataVector_detail
4154
4155
4156#endif // not XAOD_STANDALONE
4157
4158
4159
4160// We need to specialize the function that DVLInfo uses to create the container
4161// for DataVector.
4162/**
4163 * @brief Construct a new container.
4164 * @param nreserve Number of elements for which to reserve space.
4165 * (Ignored if not appropriate.)
4166 * @param cont[out] Pointer to the constructed container.
4167 * (Returned via an argument to allow for template
4168 * argument deduction.)
4169 *
4170 * Specialization for DataVector.
4171 */
4172template <class T>
4173void dvl_makecontainer (size_t nreserve, DataVector<T>*& cont)
4174{
4175 cont = new DataVector<T> (SG::VIEW_ELEMENTS);
4176 cont->reserve (nreserve);
4177}