2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5 * @file AthContainers/tools/AuxTypeVector.icc
6 * @author scott snyder <snyder@bnl.gov>
8 * @brief Implementation of @c IAuxTypeVector for specific types.
19 * @param auxid The auxid of the variable this vector represents.
20 * @param vecPtr Pointer to the object (of type @c CONT).
21 * @param ownFlag If true, take ownership of the object.
22 * @param isLinked True if this variable is linked from another one.
24 template <class T, class CONT>
26 AuxTypeVectorHolder<T, CONT>::AuxTypeVectorHolder (auxid_t auxid,
30 : IAuxTypeVector (auxid, isLinked),
39 * If @c ownFlag was true, then delete the vector object.
41 template <class T, class CONT>
43 AuxTypeVectorHolder<T, CONT>::~AuxTypeVectorHolder()
51 * @brief Copy constructor.
52 * @param other Object to copy.
54 template <class T, class CONT>
55 AuxTypeVectorHolder<T, CONT>::AuxTypeVectorHolder
56 (const AuxTypeVectorHolder& other)
57 : IAuxTypeVector (other)
59 // If we own the payload, then make a copy, else just use the same pointer.
60 m_ownFlag = other.m_ownFlag;
62 m_vecPtr = new vector_type (*other.m_vecPtr);
64 m_vecPtr = other.m_vecPtr;
69 * @brief Move constructor.
70 * @param other Object to move.
72 template <class T, class CONT>
73 AuxTypeVectorHolder<T, CONT>::AuxTypeVectorHolder (AuxTypeVectorHolder&& other)
74 : IAuxTypeVector (other)
76 m_ownFlag = other.m_ownFlag;
77 m_vecPtr = other.m_vecPtr;
78 other.m_ownFlag = false;
85 template <class T, class CONT>
86 AuxTypeVectorHolder<T, CONT>&
87 AuxTypeVectorHolder<T, CONT>::operator= (const AuxTypeVectorHolder& other)
90 IAuxTypeVector::operator= (other);
93 m_ownFlag = other.m_ownFlag;
95 m_vecPtr = new vector_type (*other.m_vecPtr);
97 m_vecPtr = other.m_vecPtr;
104 * @brief Move assignment.
106 template <class T, class CONT>
107 AuxTypeVectorHolder<T, CONT>&
108 AuxTypeVectorHolder<T, CONT>::operator= (AuxTypeVectorHolder&& other)
110 if (this != &other) {
111 IAuxTypeVector::operator= (other);
114 m_ownFlag = other.m_ownFlag;
115 m_vecPtr = other.m_vecPtr;
116 other.m_ownFlag = false;
123 * @brief Return a reference to the payload vector.
125 template <class T, class CONT>
127 typename AuxTypeVectorHolder<T, CONT>::vector_type& AuxTypeVectorHolder<T, CONT>::vec()
134 * @brief Make a copy of this vector.
136 template <class T, class CONT>
138 std::unique_ptr<IAuxTypeVector> AuxTypeVectorHolder<T, CONT>::clone() const
140 vector_type* vecPtr = new vector_type (*m_vecPtr);
141 return std::make_unique<AuxTypeVectorHolder<T, CONT> > (auxid(),
149 * @brief Return a pointer to the start of the vector's data.
151 template <class T, class CONT>
153 void* AuxTypeVectorHolder<T, CONT>::toPtr ()
155 if (m_vecPtr->empty())
157 return m_vecPtr->data();
162 * @brief Return a pointer to the start of the vector's data.
164 template <class T, class CONT>
166 const void* AuxTypeVectorHolder<T, CONT>::toPtr () const
168 if (m_vecPtr->empty())
170 return std::as_const (*m_vecPtr).data();
175 * @brief Return a pointer to the STL vector itself.
177 template <class T, class CONT>
179 void* AuxTypeVectorHolder<T, CONT>::toVector ()
186 * @brief Return the type of the complete payload object.
188 * May be different from what we get from the registry; if packing
189 * is used, for example.
191 template <class T, class CONT>
193 const std::type_info* AuxTypeVectorHolder<T, CONT>::objType() const
195 return &typeid(vector_type);
200 * @brief Return the size of the vector.
202 template <class T, class CONT>
204 size_t AuxTypeVectorHolder<T, CONT>::size () const
206 return m_vecPtr->size() / SCALE;
211 * @brief Change the size of the vector.
212 * @param sz The new vector size.
213 * Returns true if it is known that iterators have not been invalidated;
214 * false otherwise. (Will always return false when increasing the size
215 * of an empty container.)
217 template <class T, class CONT>
219 bool AuxTypeVectorHolder<T, CONT>::resize (size_t sz)
221 const void* orig = m_vecPtr->empty() ? nullptr : m_vecPtr->data();
222 m_vecPtr->resize (sz * SCALE,
223 Zero<typename AuxDataTraits<T>::element_type>::zero());
224 return m_vecPtr->data() == orig;
229 * @brief Change the capacity of the vector.
230 * @param sz The new vector capacity.
232 template <class T, class CONT>
234 void AuxTypeVectorHolder<T, CONT>::reserve (size_t sz)
236 m_vecPtr->reserve (sz * SCALE);
243 namespace DataModel_detail {
246 /// Make an option setting. VEC derives from @c IAuxSetOption.
248 bool setOptionHelper (VEC* vec, const SG::AuxDataOption& option, std::true_type)
250 SG::IAuxSetOption* setopt = static_cast<SG::IAuxSetOption*> (vec);
251 return setopt->setOption (option);
255 /// Make an option setting. VEC does not derive from @c IAuxSetOption,
256 /// so this just returns failure.
258 bool setOptionHelper (VEC* /*vec*/, const SG::AuxDataOption& /*option*/, std::false_type)
264 } // namespace DataModel_detail
271 * @brief Make an option setting.
272 * @param option The option to set.
274 * The interpretation of the option depends on the concrete class.
276 * Returns true if the option setting was successful; false otherwise.
278 template <class T, class CONT>
280 bool AuxTypeVectorHolder<T, CONT>::setOption (const AuxDataOption& option)
282 // Need to instantiate different functions depending on whether or not
283 // the payload implements @c SG::IAuxSetOption.
284 return DataModel_detail::setOptionHelper
287 typename std::is_base_of<SG::IAuxSetOption,vector_type>::type());
292 * @brief Shift the elements of the vector.
293 * @param pos The starting index for the shift.
294 * @param offs The (signed) amount of the shift.
296 * This operation shifts the elements in the vectors for all
297 * aux data items, to implement an insertion or deletion.
298 * @c offs may be either positive or negative.
300 * If @c offs is positive, then the container is growing.
301 * The container size should be increased by @c offs,
302 * the element at @c pos moved to @c pos + @c offs,
303 * and similarly for following elements.
304 * The elements between @c pos and @c pos + @c offs should
305 * be default-initialized.
307 * If @c offs is negative, then the container is shrinking.
308 * The element at @c pos should be moved to @c pos + @c offs,
309 * and similarly for following elements.
310 * The container should then be shrunk by @c -offs elements
311 * (running destructors as appropriate).
313 * Returns true if it is known that iterators have not been invalidated;
314 * false otherwise. (Will always return false when increasing the size
315 * of an empty container.)
317 template <class T, class CONT>
318 bool AuxTypeVectorHolder<T, CONT>::shift (size_t pos, ptrdiff_t offs)
320 vector_type& vec = *m_vecPtr;
322 if (-offs > static_cast<ptrdiff_t>(pos)) offs = -pos;
323 std::copy (vec.begin() + pos*SCALE,
325 vec.begin() + (pos+offs)*SCALE);
326 vec.resize (vec.size() + offs*SCALE);
330 const void* orig = vec.data();
331 size_t oldsz = vec.size();
332 // Add to the end, zero-filled.
333 vec.resize (vec.size() + offs*SCALE,
334 Zero<typename AuxDataTraits<T>::element_type>::zero());
336 // Shift existing elements. If we're just extending,
337 // then we can skip this.
338 std::copy (vec.rbegin() + offs*SCALE,
339 vec.rbegin() + (offs+oldsz-pos)*SCALE,
341 std::fill (vec.begin() + pos*SCALE,
342 vec.begin() + (pos+offs)*SCALE,
343 Zero<typename AuxDataTraits<T>::element_type>::zero());
345 return vec.data() == orig;
352 * @brief Helper for @c insertMove.
353 * @param pos The starting index of the insertion.
354 * @param beg Start of the range of elements to insert.
355 * @param end End of the range of elements to insert.
357 * This does the actual move for POD types.
359 template <class T, class CONT>
360 void AuxTypeVectorHolder<T, CONT>::insertMove1
361 (typename CONT::iterator pos,
366 m_vecPtr->insert (pos, beg, end);
371 * @brief Helper for @c insertMove.
372 * @param pos The starting index of the insertion.
373 * @param beg Start of the range of elements to insert.
374 * @param end End of the range of elements to insert.
376 * This does the actual move for non-POD types.
378 template <class T, class CONT>
379 void AuxTypeVectorHolder<T, CONT>::insertMove1
380 (typename CONT::iterator pos,
385 // std::vector doesn't provide a way to insert a range via move.
386 // So first make space, then move.
387 typename CONT::iterator pos2= m_vecPtr->insert (pos, end-beg, SG::Zero<element_type>::zero());
388 std::move (beg, end, pos2);
393 * @brief Insert elements into the vector via move semantics.
394 * @param pos The starting index of the insertion.
395 * @param beg Start of the range of elements to insert.
396 * @param end End of the range of elements to insert.
397 * @param srcStore The source store.
399 * @c beg and @c end define a range of container elements, with length
400 * @c len defined by the difference of the pointers divided by the
403 * The size of the container will be increased by @c len, with the elements
404 * starting at @c pos copied to @c pos+len.
406 * The contents of the @c beg:end range will then be moved to our vector
407 * starting at @c pos. This will be done via move semantics if possible;
408 * otherwise, it will be done with a copy.
410 * Returns true if it is known that the vector's memory did not move,
413 template <class T, class CONT>
414 bool AuxTypeVectorHolder<T, CONT>::insertMove (size_t pos, void* beg, void* end,
415 IAuxStore& /*srcStore*/)
417 const void* orig = m_vecPtr->data();
418 insertMove1 (m_vecPtr->begin() + pos*SCALE,
419 reinterpret_cast<element_type*> (beg),
420 reinterpret_cast<element_type*> (end),
421 typename std::conjunction<std::is_standard_layout<element_type>,
422 std::is_trivial<element_type> >::type());
423 return m_vecPtr->data() == orig;
430 namespace DataModel_detail {
433 /// Specialization for the case of types that can be packed.
434 template <class T, class ALLOC>
435 std::unique_ptr<SG::IAuxTypeVector> makePacked (SG::auxid_t auxid,
437 std::vector<T, ALLOC>& v,
440 // Make the new container and move our contents.
442 std::make_unique<SG::AuxTypeVector<T, ALLOC, SG::PackedContainer<T, ALLOC> > > (auxid, 0, 0, isLinked);
445 // Coverity gives a bogus complaint about the derived->base conversion here.
446 return std::unique_ptr<SG::IAuxTypeVector> (iv.release());
453 /// Specialization for the case of types that cannot be packed.
454 template <class T, class FLAG>
455 std::unique_ptr<SG::IAuxTypeVector> makePacked (SG::auxid_t, bool, T&, FLAG)
461 /// Metafunction to determine if a @c vector<T> can be packed.
462 /// Arithmetic types can be packed, as can arbitrarily-nested vectors
463 /// of them, except that integers larger than 32 bits and long double
464 /// cannot be packed.
468 typedef typename std::is_arithmetic<T>::type type;
471 struct can_pack<uint64_t>
473 typedef std::false_type type;
476 struct can_pack<int64_t>
478 typedef std::false_type type;
481 struct can_pack<long double>
483 typedef std::false_type type;
485 template <class T, class ALLOC>
486 struct can_pack<std::vector<T, ALLOC> >
488 typedef typename can_pack<T>::type type;
492 } // namespace DataModel_detail
499 * @brief Try to convert this aux vector to a @c PackedContainer.
501 * If successful, returns a newly-allocated @c IAuxTypeVector.
502 * In this case, the contents of the vector will have been moved
503 * to the new vector (and this object will be empty).
505 * Returns null on failure.
507 template <class T, class CONT>
508 std::unique_ptr<IAuxTypeVector> AuxTypeVectorHolder<T, CONT>::toPacked()
510 /// Use the proper instantiation depending on whether or not
511 /// this type can be packed.
512 return DataModel_detail::makePacked
513 (auxid(), isLinked(), *m_vecPtr, typename DataModel_detail::can_pack<T>::type());
517 //**********************************************************************
521 * @brief Constructor. Makes a new vector.
522 * @param auxid The auxid of the variable this vector represents.
523 * @param size Initial size of the new vector.
524 * @param capacity Initial capacity of the new vector.
525 * @param isLinked True if this variable is linked from another one.
527 template <class HOLDER>
528 AuxTypeVectorT<HOLDER>::AuxTypeVectorT (auxid_t auxid,
532 : Base (auxid, &m_vec, false, isLinked)
534 m_vec.reserve (capacity * Base::SCALE);
535 m_vec.resize (size * Base::SCALE);
540 * @brief Copy constructor.
542 template <class HOLDER>
543 AuxTypeVectorT<HOLDER>::AuxTypeVectorT (const AuxTypeVectorT& other)
544 : Base (other.auxid(), &m_vec, false, other.isLinked()),
551 * @brief Move constructor.
553 template <class HOLDER>
554 AuxTypeVectorT<HOLDER>::AuxTypeVectorT (AuxTypeVectorT&& other)
555 : Base (other.auxid(), &m_vec, false, other.isLinked()),
556 m_vec (std::move (other.m_vec))
564 template <class HOLDER>
565 AuxTypeVectorT<HOLDER>&
566 AuxTypeVectorT<HOLDER>::operator= (const AuxTypeVectorT& other)
568 if (this != &other) {
569 Base::IAuxTypeVector::operator= (other);
577 * @brief Move assignment.
579 template <class HOLDER>
580 AuxTypeVectorT<HOLDER>&
581 AuxTypeVectorT<HOLDER>::operator= (AuxTypeVectorT&& other)
583 if (this != &other) {
584 Base::IAuxTypeVector::operator= (other);
585 m_vec = std::move (other.m_vec);
592 * @brief Make a copy of this vector.
594 template <class HOLDER>
596 std::unique_ptr<IAuxTypeVector> AuxTypeVectorT<HOLDER>::clone() const
598 return std::make_unique<AuxTypeVectorT> (*this);